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, 2017, 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 <uapi/linux/lustre/lustre_ioctl.h>
46 #include <uapi/linux/lustre/lustre_param.h>
47 #include <lustre_sec.h>
48 #include <lustre_quota.h>
49 #include <lustre_sec.h>
51 #include "mgs_internal.h"
53 /********************** Class functions ********************/
56 * Find all logs in CONFIG directory and link then into list.
58 * \param[in] env pointer to the thread context
59 * \param[in] mgs pointer to the mgs device
60 * \param[out] log_list the list to hold the found llog name entry
62 * \retval 0 for success
63 * \retval negative error number on failure
65 int class_dentry_readdir(const struct lu_env *env, struct mgs_device *mgs,
66 struct list_head *log_list)
68 struct dt_object *dir = mgs->mgs_configs_dir;
69 const struct dt_it_ops *iops;
71 struct mgs_direntry *de;
75 INIT_LIST_HEAD(log_list);
78 LASSERT(dir->do_index_ops);
80 iops = &dir->do_index_ops->dio_it;
81 it = iops->init(env, dir, LUDA_64BITHASH);
85 rc = iops->load(env, it, 0);
91 key = (void *)iops->key(env, it);
93 CERROR("%s: key failed when listing %s: rc = %d\n",
94 mgs->mgs_obd->obd_name, MOUNT_CONFIGS_DIR,
98 key_sz = iops->key_size(env, it);
101 /* filter out "." and ".." entries */
105 if (key_sz == 2 && key[1] == '.')
109 /* filter out ".bak" files */
110 /* sizeof(".bak") - 1 == 3 */
112 !memcmp(".bak", key + key_sz - 3, 3)) {
113 CDEBUG(D_MGS, "Skipping backup file %.*s\n",
118 de = mgs_direntry_alloc(key_sz + 1);
124 memcpy(de->mde_name, key, key_sz);
125 de->mde_name[key_sz] = 0;
127 list_add(&de->mde_list, log_list);
130 rc = iops->next(env, it);
140 struct mgs_direntry *n;
142 CERROR("%s: key failed when listing %s: rc = %d\n",
143 mgs->mgs_obd->obd_name, MOUNT_CONFIGS_DIR, rc);
145 list_for_each_entry_safe(de, n, log_list, mde_list) {
146 list_del_init(&de->mde_list);
147 mgs_direntry_free(de);
154 /******************** DB functions *********************/
156 static inline int name_create(char **newname, char *prefix, char *suffix)
159 OBD_ALLOC(*newname, strlen(prefix) + strlen(suffix) + 1);
162 sprintf(*newname, "%s%s", prefix, suffix);
166 static inline void name_destroy(char **name)
169 OBD_FREE(*name, strlen(*name) + 1);
173 struct mgs_fsdb_handler_data
179 /* from the (client) config log, figure out:
180 1. which ost's/mdt's are configured (by index)
181 2. what the last config step is
182 3. COMPAT_18 osc name
184 /* It might be better to have a separate db file, instead of parsing the info
185 out of the client log. This is slow and potentially error-prone. */
186 static int mgs_fsdb_handler(const struct lu_env *env, struct llog_handle *llh,
187 struct llog_rec_hdr *rec, void *data)
189 struct mgs_fsdb_handler_data *d = data;
190 struct fs_db *fsdb = d->fsdb;
191 int cfg_len = rec->lrh_len;
192 char *cfg_buf = (char*) (rec + 1);
193 struct lustre_cfg *lcfg;
198 if (rec->lrh_type != OBD_CFG_REC) {
199 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
203 rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
205 CERROR("Insane cfg\n");
209 lcfg = (struct lustre_cfg *)cfg_buf;
211 CDEBUG(D_INFO, "cmd %x %s %s\n", lcfg->lcfg_command,
212 lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
214 /* Figure out ost indicies */
215 /* lov_modify_tgts add 0:lov1 1:ost1_UUID 2(index):0 3(gen):1 */
216 if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD ||
217 lcfg->lcfg_command == LCFG_LOV_DEL_OBD) {
218 index = simple_strtoul(lustre_cfg_string(lcfg, 2),
220 CDEBUG(D_MGS, "OST index for %s is %u (%s)\n",
221 lustre_cfg_string(lcfg, 1), index,
222 lustre_cfg_string(lcfg, 2));
223 set_bit(index, fsdb->fsdb_ost_index_map);
226 /* Figure out mdt indicies */
227 /* attach 0:MDC_uml1_mdsA_MNT_client 1:mdc 2:1d834_MNT_client_03f */
228 if ((lcfg->lcfg_command == LCFG_ATTACH) &&
229 (strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_MDC_NAME) == 0)) {
230 rc = server_name2index(lustre_cfg_string(lcfg, 0),
232 if (rc != LDD_F_SV_TYPE_MDT) {
233 CWARN("Unparsable MDC name %s, assuming index 0\n",
234 lustre_cfg_string(lcfg, 0));
238 CDEBUG(D_MGS, "MDT index is %u\n", index);
239 if (!test_bit(index, fsdb->fsdb_mdt_index_map)) {
240 set_bit(index, fsdb->fsdb_mdt_index_map);
241 fsdb->fsdb_mdt_count++;
246 * figure out the old config. fsdb_gen = 0 means old log
247 * It is obsoleted and not supported anymore
249 if (fsdb->fsdb_gen == 0) {
250 CERROR("Old config format is not supported\n");
255 * compat to 1.8, check osc name used by MDT0 to OSTs, bz18548.
257 if (!test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags) &&
258 lcfg->lcfg_command == LCFG_ATTACH &&
259 strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_OSC_NAME) == 0) {
260 if (OBD_OCD_VERSION_MAJOR(d->ver) == 1 &&
261 OBD_OCD_VERSION_MINOR(d->ver) <= 8) {
262 CWARN("MDT using 1.8 OSC name scheme\n");
263 set_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags);
267 if (lcfg->lcfg_command == LCFG_MARKER) {
268 struct cfg_marker *marker;
269 marker = lustre_cfg_buf(lcfg, 1);
271 d->ver = marker->cm_vers;
273 /* Keep track of the latest marker step */
274 fsdb->fsdb_gen = max(fsdb->fsdb_gen, marker->cm_step);
280 /* fsdb->fsdb_mutex is already held in mgs_find_or_make_fsdb*/
281 static int mgs_get_fsdb_from_llog(const struct lu_env *env,
282 struct mgs_device *mgs,
286 struct llog_handle *loghandle;
287 struct llog_ctxt *ctxt;
288 struct mgs_fsdb_handler_data d = {
295 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
296 LASSERT(ctxt != NULL);
297 rc = name_create(&logname, fsdb->fsdb_name, "-client");
300 rc = llog_open_create(env, ctxt, &loghandle, NULL, logname);
304 rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
308 if (llog_get_size(loghandle) <= 1)
309 set_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags);
311 rc = llog_process(env, loghandle, mgs_fsdb_handler, (void *)&d, NULL);
312 CDEBUG(D_INFO, "get_db = %d\n", rc);
314 llog_close(env, loghandle);
316 name_destroy(&logname);
323 static void mgs_free_fsdb_srpc(struct fs_db *fsdb)
325 struct mgs_tgt_srpc_conf *tgtconf;
327 /* free target-specific rules */
328 while (fsdb->fsdb_srpc_tgt) {
329 tgtconf = fsdb->fsdb_srpc_tgt;
330 fsdb->fsdb_srpc_tgt = tgtconf->mtsc_next;
332 LASSERT(tgtconf->mtsc_tgt);
334 sptlrpc_rule_set_free(&tgtconf->mtsc_rset);
335 OBD_FREE(tgtconf->mtsc_tgt, strlen(tgtconf->mtsc_tgt) + 1);
336 OBD_FREE_PTR(tgtconf);
339 /* free general rules */
340 sptlrpc_rule_set_free(&fsdb->fsdb_srpc_gen);
343 static void mgs_unlink_fsdb(struct mgs_device *mgs, struct fs_db *fsdb)
345 mutex_lock(&mgs->mgs_mutex);
346 if (likely(!list_empty(&fsdb->fsdb_list))) {
347 LASSERTF(atomic_read(&fsdb->fsdb_ref) >= 2,
348 "Invalid ref %d on %s\n",
349 atomic_read(&fsdb->fsdb_ref),
352 list_del_init(&fsdb->fsdb_list);
353 /* Drop the reference on the list.*/
354 mgs_put_fsdb(mgs, fsdb);
356 mutex_unlock(&mgs->mgs_mutex);
359 /* The caller must hold mgs->mgs_mutex. */
360 static inline struct fs_db *
361 mgs_find_fsdb_noref(struct mgs_device *mgs, const char *fsname)
364 struct list_head *tmp;
366 list_for_each(tmp, &mgs->mgs_fs_db_list) {
367 fsdb = list_entry(tmp, struct fs_db, fsdb_list);
368 if (strcmp(fsdb->fsdb_name, fsname) == 0)
375 /* The caller must hold mgs->mgs_mutex. */
376 static void mgs_remove_fsdb_by_name(struct mgs_device *mgs, const char *name)
380 fsdb = mgs_find_fsdb_noref(mgs, name);
382 list_del_init(&fsdb->fsdb_list);
383 /* Drop the reference on the list.*/
384 mgs_put_fsdb(mgs, fsdb);
388 /* The caller must hold mgs->mgs_mutex. */
389 struct fs_db *mgs_find_fsdb(struct mgs_device *mgs, const char *fsname)
393 fsdb = mgs_find_fsdb_noref(mgs, fsname);
395 atomic_inc(&fsdb->fsdb_ref);
400 /* The caller must hold mgs->mgs_mutex. */
401 static struct fs_db *mgs_new_fsdb(const struct lu_env *env,
402 struct mgs_device *mgs, char *fsname)
408 if (strlen(fsname) >= sizeof(fsdb->fsdb_name)) {
409 CERROR("fsname %s is too long\n", fsname);
411 RETURN(ERR_PTR(-EINVAL));
416 RETURN(ERR_PTR(-ENOMEM));
418 strncpy(fsdb->fsdb_name, fsname, sizeof(fsdb->fsdb_name));
419 mutex_init(&fsdb->fsdb_mutex);
420 INIT_LIST_HEAD(&fsdb->fsdb_list);
421 set_bit(FSDB_UDESC, &fsdb->fsdb_flags);
423 INIT_LIST_HEAD(&fsdb->fsdb_clients);
424 atomic_set(&fsdb->fsdb_notify_phase, 0);
425 init_waitqueue_head(&fsdb->fsdb_notify_waitq);
426 init_completion(&fsdb->fsdb_notify_comp);
428 if (strcmp(fsname, MGSSELF_NAME) == 0) {
429 set_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags);
430 fsdb->fsdb_mgs = mgs;
431 if (logname_is_barrier(fsname))
434 OBD_ALLOC(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
435 if (!fsdb->fsdb_mdt_index_map) {
436 CERROR("No memory for MDT index maps\n");
438 GOTO(err, rc = -ENOMEM);
441 OBD_ALLOC(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
442 if (!fsdb->fsdb_ost_index_map) {
443 CERROR("No memory for OST index maps\n");
445 GOTO(err, rc = -ENOMEM);
448 if (logname_is_barrier(fsname))
451 rc = name_create(&fsdb->fsdb_clilov, fsname, "-clilov");
455 rc = name_create(&fsdb->fsdb_clilmv, fsname, "-clilmv");
459 /* initialise data for NID table */
460 mgs_ir_init_fs(env, mgs, fsdb);
461 lproc_mgs_add_live(mgs, fsdb);
464 if (!test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags) &&
465 strcmp(PARAMS_FILENAME, fsname) != 0) {
466 /* populate the db from the client llog */
467 rc = mgs_get_fsdb_from_llog(env, mgs, fsdb);
469 CERROR("Can't get db from client log %d\n", rc);
475 /* populate srpc rules from params llog */
476 rc = mgs_get_fsdb_srpc_from_llog(env, mgs, fsdb);
478 CERROR("Can't get db from params log %d\n", rc);
484 /* One ref is for the fsdb on the list.
485 * The other ref is for the caller. */
486 atomic_set(&fsdb->fsdb_ref, 2);
487 list_add(&fsdb->fsdb_list, &mgs->mgs_fs_db_list);
492 atomic_set(&fsdb->fsdb_ref, 1);
493 mgs_put_fsdb(mgs, fsdb);
498 static void mgs_free_fsdb(struct mgs_device *mgs, struct fs_db *fsdb)
500 LASSERT(list_empty(&fsdb->fsdb_list));
502 lproc_mgs_del_live(mgs, fsdb);
504 /* deinitialize fsr */
506 mgs_ir_fini_fs(mgs, fsdb);
508 if (fsdb->fsdb_ost_index_map)
509 OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
510 if (fsdb->fsdb_mdt_index_map)
511 OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
512 name_destroy(&fsdb->fsdb_clilov);
513 name_destroy(&fsdb->fsdb_clilmv);
514 mgs_free_fsdb_srpc(fsdb);
518 void mgs_put_fsdb(struct mgs_device *mgs, struct fs_db *fsdb)
520 if (atomic_dec_and_test(&fsdb->fsdb_ref))
521 mgs_free_fsdb(mgs, fsdb);
524 int mgs_init_fsdb_list(struct mgs_device *mgs)
526 INIT_LIST_HEAD(&mgs->mgs_fs_db_list);
530 int mgs_cleanup_fsdb_list(struct mgs_device *mgs)
533 struct list_head *tmp, *tmp2;
535 mutex_lock(&mgs->mgs_mutex);
536 list_for_each_safe(tmp, tmp2, &mgs->mgs_fs_db_list) {
537 fsdb = list_entry(tmp, struct fs_db, fsdb_list);
538 list_del_init(&fsdb->fsdb_list);
539 mgs_put_fsdb(mgs, fsdb);
541 mutex_unlock(&mgs->mgs_mutex);
545 /* The caller must hold mgs->mgs_mutex. */
546 int mgs_find_or_make_fsdb_nolock(const struct lu_env *env,
547 struct mgs_device *mgs,
548 char *name, struct fs_db **dbh)
554 fsdb = mgs_find_fsdb(mgs, name);
556 fsdb = mgs_new_fsdb(env, mgs, name);
560 CDEBUG(D_MGS, "Created new db: rc = %d\n", rc);
569 int mgs_find_or_make_fsdb(const struct lu_env *env, struct mgs_device *mgs,
570 char *name, struct fs_db **dbh)
575 mutex_lock(&mgs->mgs_mutex);
576 rc = mgs_find_or_make_fsdb_nolock(env, mgs, name, dbh);
577 mutex_unlock(&mgs->mgs_mutex);
584 -1= empty client log */
585 int mgs_check_index(const struct lu_env *env,
586 struct mgs_device *mgs,
587 struct mgs_target_info *mti)
594 LASSERT(!(mti->mti_flags & LDD_F_NEED_INDEX));
596 rc = mgs_find_or_make_fsdb(env, mgs, mti->mti_fsname, &fsdb);
598 CERROR("Can't get db for %s\n", mti->mti_fsname);
602 if (test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags))
605 if (mti->mti_flags & LDD_F_SV_TYPE_OST)
606 imap = fsdb->fsdb_ost_index_map;
607 else if (mti->mti_flags & LDD_F_SV_TYPE_MDT)
608 imap = fsdb->fsdb_mdt_index_map;
610 GOTO(out, rc = -EINVAL);
612 if (test_bit(mti->mti_stripe_index, imap))
618 mgs_put_fsdb(mgs, fsdb);
622 static __inline__ int next_index(void *index_map, int map_len)
625 for (i = 0; i < map_len * 8; i++)
626 if (!test_bit(i, index_map)) {
629 CERROR("max index %d exceeded.\n", i);
633 /* Make the mdt/ost server obd name based on the filesystem name */
634 static bool server_make_name(u32 flags, u16 index, const char *fs,
635 char *name_buf, size_t name_buf_size)
637 bool invalid_flag = false;
639 if (flags & (LDD_F_SV_TYPE_MDT | LDD_F_SV_TYPE_OST)) {
640 if (!(flags & LDD_F_SV_ALL))
641 snprintf(name_buf, name_buf_size, "%.8s%c%s%04x", fs,
642 (flags & LDD_F_VIRGIN) ? ':' :
643 ((flags & LDD_F_WRITECONF) ? '=' : '-'),
644 (flags & LDD_F_SV_TYPE_MDT) ? "MDT" : "OST",
646 } else if (flags & LDD_F_SV_TYPE_MGS) {
647 snprintf(name_buf, name_buf_size, "MGS");
649 CERROR("unknown server type %#x\n", flags);
656 0 newly marked as in use
658 +EALREADY for update of an old index */
659 static int mgs_set_index(const struct lu_env *env,
660 struct mgs_device *mgs,
661 struct mgs_target_info *mti)
668 rc = mgs_find_or_make_fsdb(env, mgs, mti->mti_fsname, &fsdb);
670 CERROR("Can't get db for %s\n", mti->mti_fsname);
674 mutex_lock(&fsdb->fsdb_mutex);
675 if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
676 imap = fsdb->fsdb_ost_index_map;
677 } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
678 imap = fsdb->fsdb_mdt_index_map;
680 GOTO(out_up, rc = -EINVAL);
683 if (mti->mti_flags & LDD_F_NEED_INDEX) {
684 rc = next_index(imap, INDEX_MAP_SIZE);
686 GOTO(out_up, rc = -ERANGE);
687 mti->mti_stripe_index = rc;
690 /* the last index(0xffff) is reserved for default value. */
691 if (mti->mti_stripe_index >= INDEX_MAP_SIZE * 8 - 1) {
692 LCONSOLE_ERROR_MSG(0x13f, "Server %s requested index %u, "
693 "but index must be less than %u.\n",
694 mti->mti_svname, mti->mti_stripe_index,
695 INDEX_MAP_SIZE * 8 - 1);
696 GOTO(out_up, rc = -ERANGE);
699 if (test_bit(mti->mti_stripe_index, imap)) {
700 if ((mti->mti_flags & LDD_F_VIRGIN) &&
701 !(mti->mti_flags & LDD_F_WRITECONF)) {
702 LCONSOLE_ERROR_MSG(0x140, "Server %s requested index "
703 "%d, but that index is already in "
704 "use. Use --writeconf to force\n",
706 mti->mti_stripe_index);
707 GOTO(out_up, rc = -EADDRINUSE);
709 CDEBUG(D_MGS, "Server %s updating index %d\n",
710 mti->mti_svname, mti->mti_stripe_index);
711 GOTO(out_up, rc = EALREADY);
714 set_bit(mti->mti_stripe_index, imap);
715 if (mti->mti_flags & LDD_F_SV_TYPE_MDT)
716 fsdb->fsdb_mdt_count++;
719 set_bit(mti->mti_stripe_index, imap);
720 clear_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags);
721 if (server_make_name(mti->mti_flags & ~(LDD_F_VIRGIN | LDD_F_WRITECONF),
722 mti->mti_stripe_index, mti->mti_fsname,
723 mti->mti_svname, sizeof(mti->mti_svname))) {
724 CERROR("unknown server type %#x\n", mti->mti_flags);
725 GOTO(out_up, rc = -EINVAL);
728 CDEBUG(D_MGS, "Set index for %s to %d\n", mti->mti_svname,
729 mti->mti_stripe_index);
731 GOTO(out_up, rc = 0);
734 mutex_unlock(&fsdb->fsdb_mutex);
735 mgs_put_fsdb(mgs, fsdb);
739 struct mgs_modify_lookup {
740 struct cfg_marker mml_marker;
744 static int mgs_check_record_match(const struct lu_env *env,
745 struct llog_handle *llh,
746 struct llog_rec_hdr *rec, void *data)
748 struct cfg_marker *mc_marker = data;
749 struct cfg_marker *marker;
750 struct lustre_cfg *lcfg = REC_DATA(rec);
751 int cfg_len = REC_DATA_LEN(rec);
756 if (rec->lrh_type != OBD_CFG_REC) {
757 CDEBUG(D_ERROR, "Unhandled lrh_type: %#x\n", rec->lrh_type);
761 rc = lustre_cfg_sanity_check(lcfg, cfg_len);
763 CDEBUG(D_ERROR, "Insane cfg\n");
767 /* We only care about markers */
768 if (lcfg->lcfg_command != LCFG_MARKER)
771 marker = lustre_cfg_buf(lcfg, 1);
773 if (marker->cm_flags & CM_SKIP)
776 if ((strcmp(mc_marker->cm_comment, marker->cm_comment) == 0) &&
777 (strcmp(mc_marker->cm_tgtname, marker->cm_tgtname) == 0)) {
778 /* Found a non-skipped marker match */
779 CDEBUG(D_MGS, "Matched rec %u marker %d flag %x %s %s\n",
780 rec->lrh_index, marker->cm_step,
781 marker->cm_flags, marker->cm_tgtname,
783 rc = LLOG_PROC_BREAK;
790 * Check an existing config log record with matching comment and device
792 * 0 - checked successfully,
793 * LLOG_PROC_BREAK - record matches
796 static int mgs_check_marker(const struct lu_env *env, struct mgs_device *mgs,
797 struct fs_db *fsdb, struct mgs_target_info *mti,
798 char *logname, char *devname, char *comment)
800 struct llog_handle *loghandle;
801 struct llog_ctxt *ctxt;
802 struct cfg_marker *mc_marker;
807 LASSERT(mutex_is_locked(&fsdb->fsdb_mutex));
808 CDEBUG(D_MGS, "mgs check %s/%s/%s\n", logname, devname, comment);
810 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
811 LASSERT(ctxt != NULL);
812 rc = llog_open(env, ctxt, &loghandle, NULL, logname, LLOG_OPEN_EXISTS);
819 rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
823 if (llog_get_size(loghandle) <= 1)
824 GOTO(out_close, rc = 0);
826 OBD_ALLOC_PTR(mc_marker);
828 GOTO(out_close, rc = -ENOMEM);
829 if (strlcpy(mc_marker->cm_comment, comment,
830 sizeof(mc_marker->cm_comment)) >=
831 sizeof(mc_marker->cm_comment))
832 GOTO(out_free, rc = -E2BIG);
833 if (strlcpy(mc_marker->cm_tgtname, devname,
834 sizeof(mc_marker->cm_tgtname)) >=
835 sizeof(mc_marker->cm_tgtname))
836 GOTO(out_free, rc = -E2BIG);
838 rc = llog_process(env, loghandle, mgs_check_record_match,
839 (void *)mc_marker, NULL);
842 OBD_FREE_PTR(mc_marker);
845 llog_close(env, loghandle);
847 if (rc && rc != LLOG_PROC_BREAK)
848 CDEBUG(D_ERROR, "%s: mgs check %s/%s failed: rc = %d\n",
849 mgs->mgs_obd->obd_name, mti->mti_svname, comment, rc);
854 static int mgs_modify_handler(const struct lu_env *env,
855 struct llog_handle *llh,
856 struct llog_rec_hdr *rec, void *data)
858 struct mgs_modify_lookup *mml = data;
859 struct cfg_marker *marker;
860 struct lustre_cfg *lcfg = REC_DATA(rec);
861 int cfg_len = REC_DATA_LEN(rec);
865 if (rec->lrh_type != OBD_CFG_REC) {
866 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
870 rc = lustre_cfg_sanity_check(lcfg, cfg_len);
872 CERROR("Insane cfg\n");
876 /* We only care about markers */
877 if (lcfg->lcfg_command != LCFG_MARKER)
880 marker = lustre_cfg_buf(lcfg, 1);
881 if ((strcmp(mml->mml_marker.cm_comment, marker->cm_comment) == 0) &&
882 (strcmp(mml->mml_marker.cm_tgtname, marker->cm_tgtname) == 0) &&
883 !(marker->cm_flags & CM_SKIP)) {
884 /* Found a non-skipped marker match */
885 CDEBUG(D_MGS, "Changing rec %u marker %d %x->%x: %s %s\n",
886 rec->lrh_index, marker->cm_step,
887 marker->cm_flags, mml->mml_marker.cm_flags,
888 marker->cm_tgtname, marker->cm_comment);
889 /* Overwrite the old marker llog entry */
890 marker->cm_flags &= ~CM_EXCLUDE; /* in case we're unexcluding */
891 marker->cm_flags |= mml->mml_marker.cm_flags;
892 marker->cm_canceltime = mml->mml_marker.cm_canceltime;
893 rc = llog_write(env, llh, rec, rec->lrh_index);
902 * Modify an existing config log record (for CM_SKIP or CM_EXCLUDE)
904 * 0 - modified successfully,
905 * 1 - no modification was done
908 static int mgs_modify(const struct lu_env *env, struct mgs_device *mgs,
909 struct fs_db *fsdb, struct mgs_target_info *mti,
910 char *logname, char *devname, char *comment, int flags)
912 struct llog_handle *loghandle;
913 struct llog_ctxt *ctxt;
914 struct mgs_modify_lookup *mml;
919 LASSERT(mutex_is_locked(&fsdb->fsdb_mutex));
920 CDEBUG(D_MGS, "modify %s/%s/%s fl=%x\n", logname, devname, comment,
923 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
924 LASSERT(ctxt != NULL);
925 rc = llog_open(env, ctxt, &loghandle, NULL, logname, LLOG_OPEN_EXISTS);
932 rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
936 if (llog_get_size(loghandle) <= 1)
937 GOTO(out_close, rc = 0);
941 GOTO(out_close, rc = -ENOMEM);
942 if (strlcpy(mml->mml_marker.cm_comment, comment,
943 sizeof(mml->mml_marker.cm_comment)) >=
944 sizeof(mml->mml_marker.cm_comment))
945 GOTO(out_free, rc = -E2BIG);
946 if (strlcpy(mml->mml_marker.cm_tgtname, devname,
947 sizeof(mml->mml_marker.cm_tgtname)) >=
948 sizeof(mml->mml_marker.cm_tgtname))
949 GOTO(out_free, rc = -E2BIG);
950 /* Modify mostly means cancel */
951 mml->mml_marker.cm_flags = flags;
952 mml->mml_marker.cm_canceltime = flags ? ktime_get_real_seconds() : 0;
953 mml->mml_modified = 0;
954 rc = llog_process(env, loghandle, mgs_modify_handler, (void *)mml,
956 if (!rc && !mml->mml_modified)
963 llog_close(env, loghandle);
966 CERROR("%s: modify %s/%s failed: rc = %d\n",
967 mgs->mgs_obd->obd_name, mti->mti_svname, comment, rc);
972 /** This structure is passed to mgs_replace_handler */
973 struct mgs_replace_data {
974 /* Nids are replaced for this target device */
975 struct mgs_target_info target;
976 /* Temporary modified llog */
977 struct llog_handle *temp_llh;
978 /* Flag is set if in target block*/
979 int in_target_device;
980 /* Nids already added. Just skip (multiple nids) */
981 int device_nids_added;
982 /* Flag is set if this block should not be copied */
987 * Check: a) if block should be skipped
988 * b) is it target block
993 * \retval 0 should not to be skipped
994 * \retval 1 should to be skipped
996 static int check_markers(struct lustre_cfg *lcfg,
997 struct mgs_replace_data *mrd)
999 struct cfg_marker *marker;
1001 /* Track markers. Find given device */
1002 if (lcfg->lcfg_command == LCFG_MARKER) {
1003 marker = lustre_cfg_buf(lcfg, 1);
1004 /* Clean llog from records marked as CM_SKIP.
1005 CM_EXCLUDE records are used for "active" command
1006 and can be restored if needed */
1007 if ((marker->cm_flags & (CM_SKIP | CM_START)) ==
1008 (CM_SKIP | CM_START)) {
1013 if ((marker->cm_flags & (CM_SKIP | CM_END)) ==
1014 (CM_SKIP | CM_END)) {
1019 if (strcmp(mrd->target.mti_svname, marker->cm_tgtname) == 0) {
1020 LASSERT(!(marker->cm_flags & CM_START) ||
1021 !(marker->cm_flags & CM_END));
1022 if (marker->cm_flags & CM_START) {
1023 mrd->in_target_device = 1;
1024 mrd->device_nids_added = 0;
1025 } else if (marker->cm_flags & CM_END)
1026 mrd->in_target_device = 0;
1033 static int record_base(const struct lu_env *env, struct llog_handle *llh,
1034 char *cfgname, lnet_nid_t nid, int cmd,
1035 char *s1, char *s2, char *s3, char *s4)
1037 struct mgs_thread_info *mgi = mgs_env_info(env);
1038 struct llog_cfg_rec *lcr;
1041 CDEBUG(D_MGS, "lcfg %s %#x %s %s %s %s\n", cfgname,
1042 cmd, s1, s2, s3, s4);
1044 lustre_cfg_bufs_reset(&mgi->mgi_bufs, cfgname);
1046 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, s1);
1048 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 2, s2);
1050 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 3, s3);
1052 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 4, s4);
1054 lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
1058 lcr->lcr_cfg.lcfg_nid = nid;
1059 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1061 lustre_cfg_rec_free(lcr);
1065 "failed to write lcfg %s %#x %s %s %s %s: rc = %d\n",
1066 cfgname, cmd, s1, s2, s3, s4, rc);
1070 static inline int record_add_uuid(const struct lu_env *env,
1071 struct llog_handle *llh,
1072 uint64_t nid, char *uuid)
1074 return record_base(env, llh, NULL, nid, LCFG_ADD_UUID, uuid,
1078 static inline int record_add_conn(const struct lu_env *env,
1079 struct llog_handle *llh,
1080 char *devname, char *uuid)
1082 return record_base(env, llh, devname, 0, LCFG_ADD_CONN, uuid,
1086 static inline int record_attach(const struct lu_env *env,
1087 struct llog_handle *llh, char *devname,
1088 char *type, char *uuid)
1090 return record_base(env, llh, devname, 0, LCFG_ATTACH, type, uuid,
1094 static inline int record_setup(const struct lu_env *env,
1095 struct llog_handle *llh, char *devname,
1096 char *s1, char *s2, char *s3, char *s4)
1098 return record_base(env, llh, devname, 0, LCFG_SETUP, s1, s2, s3, s4);
1102 * \retval <0 record processing error
1103 * \retval n record is processed. No need copy original one.
1104 * \retval 0 record is not processed.
1106 static int process_command(const struct lu_env *env, struct lustre_cfg *lcfg,
1107 struct mgs_replace_data *mrd)
1114 if (lcfg->lcfg_command == LCFG_ADD_UUID) {
1115 /* LCFG_ADD_UUID command found. Let's skip original command
1116 and add passed nids */
1117 ptr = mrd->target.mti_params;
1118 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
1119 CDEBUG(D_MGS, "add nid %s with uuid %s, "
1120 "device %s\n", libcfs_nid2str(nid),
1121 mrd->target.mti_params,
1122 mrd->target.mti_svname);
1123 rc = record_add_uuid(env,
1125 mrd->target.mti_params);
1130 if (nids_added == 0) {
1131 CERROR("No new nids were added, nid %s with uuid %s, "
1132 "device %s\n", libcfs_nid2str(nid),
1133 mrd->target.mti_params,
1134 mrd->target.mti_svname);
1137 mrd->device_nids_added = 1;
1143 if (mrd->device_nids_added && lcfg->lcfg_command == LCFG_SETUP) {
1144 /* LCFG_SETUP command found. UUID should be changed */
1145 rc = record_setup(env,
1147 /* devname the same */
1148 lustre_cfg_string(lcfg, 0),
1149 /* s1 is not changed */
1150 lustre_cfg_string(lcfg, 1),
1151 /* new uuid should be
1153 mrd->target.mti_params,
1154 /* s3 is not changed */
1155 lustre_cfg_string(lcfg, 3),
1156 /* s4 is not changed */
1157 lustre_cfg_string(lcfg, 4));
1161 /* Another commands in target device block */
1166 * Handler that called for every record in llog.
1167 * Records are processed in order they placed in llog.
1169 * \param[in] llh log to be processed
1170 * \param[in] rec current record
1171 * \param[in] data mgs_replace_data structure
1175 static int mgs_replace_nids_handler(const struct lu_env *env,
1176 struct llog_handle *llh,
1177 struct llog_rec_hdr *rec,
1180 struct mgs_replace_data *mrd;
1181 struct lustre_cfg *lcfg = REC_DATA(rec);
1182 int cfg_len = REC_DATA_LEN(rec);
1186 mrd = (struct mgs_replace_data *)data;
1188 if (rec->lrh_type != OBD_CFG_REC) {
1189 CERROR("unhandled lrh_type: %#x, cmd %x %s %s\n",
1190 rec->lrh_type, lcfg->lcfg_command,
1191 lustre_cfg_string(lcfg, 0),
1192 lustre_cfg_string(lcfg, 1));
1196 rc = lustre_cfg_sanity_check(lcfg, cfg_len);
1198 /* Do not copy any invalidated records */
1199 GOTO(skip_out, rc = 0);
1202 rc = check_markers(lcfg, mrd);
1203 if (rc || mrd->skip_it)
1204 GOTO(skip_out, rc = 0);
1206 /* Write to new log all commands outside target device block */
1207 if (!mrd->in_target_device)
1208 GOTO(copy_out, rc = 0);
1210 /* Skip all other LCFG_ADD_UUID and LCFG_ADD_CONN records
1211 (failover nids) for this target, assuming that if then
1212 primary is changing then so is the failover */
1213 if (mrd->device_nids_added &&
1214 (lcfg->lcfg_command == LCFG_ADD_UUID ||
1215 lcfg->lcfg_command == LCFG_ADD_CONN))
1216 GOTO(skip_out, rc = 0);
1218 rc = process_command(env, lcfg, mrd);
1225 /* Record is placed in temporary llog as is */
1226 rc = llog_write(env, mrd->temp_llh, rec, LLOG_NEXT_IDX);
1228 CDEBUG(D_MGS, "Copied idx=%d, rc=%d, len=%d, cmd %x %s %s\n",
1229 rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
1230 lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
1234 CDEBUG(D_MGS, "Skipped idx=%d, rc=%d, len=%d, cmd %x %s %s\n",
1235 rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
1236 lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
1240 static int mgs_log_is_empty(const struct lu_env *env,
1241 struct mgs_device *mgs, char *name)
1243 struct llog_ctxt *ctxt;
1246 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
1247 LASSERT(ctxt != NULL);
1249 rc = llog_is_empty(env, ctxt, name);
1250 llog_ctxt_put(ctxt);
1254 static int mgs_replace_log(const struct lu_env *env,
1255 struct obd_device *mgs,
1256 char *logname, char *devname,
1257 llog_cb_t replace_handler, void *data)
1259 struct llog_handle *orig_llh, *backup_llh;
1260 struct llog_ctxt *ctxt;
1261 struct mgs_replace_data *mrd;
1262 struct mgs_device *mgs_dev = lu2mgs_dev(mgs->obd_lu_dev);
1263 static struct obd_uuid cfg_uuid = { .uuid = "config_uuid" };
1265 int rc, rc2, buf_size;
1269 ctxt = llog_get_context(mgs, LLOG_CONFIG_ORIG_CTXT);
1270 LASSERT(ctxt != NULL);
1272 if (mgs_log_is_empty(env, mgs_dev, logname)) {
1273 /* Log is empty. Nothing to replace */
1274 GOTO(out_put, rc = 0);
1277 now = ktime_get_real_seconds();
1279 /* max time64_t in decimal fits into 20 bytes long string */
1280 buf_size = strlen(logname) + 1 + 20 + 1 + strlen(".bak") + 1;
1281 OBD_ALLOC(backup, buf_size);
1283 GOTO(out_put, rc = -ENOMEM);
1285 snprintf(backup, buf_size, "%s.%llu.bak", logname, now);
1287 rc = llog_backup(env, mgs, ctxt, ctxt, logname, backup);
1289 /* Now erase original log file. Connections are not allowed.
1290 Backup is already saved */
1291 rc = llog_erase(env, ctxt, NULL, logname);
1294 } else if (rc != -ENOENT) {
1295 CERROR("%s: can't make backup for %s: rc = %d\n",
1296 mgs->obd_name, logname, rc);
1300 /* open local log */
1301 rc = llog_open_create(env, ctxt, &orig_llh, NULL, logname);
1303 GOTO(out_restore, rc);
1305 rc = llog_init_handle(env, orig_llh, LLOG_F_IS_PLAIN, &cfg_uuid);
1307 GOTO(out_closel, rc);
1309 /* open backup llog */
1310 rc = llog_open(env, ctxt, &backup_llh, NULL, backup,
1313 GOTO(out_closel, rc);
1315 rc = llog_init_handle(env, backup_llh, LLOG_F_IS_PLAIN, NULL);
1317 GOTO(out_close, rc);
1319 if (llog_get_size(backup_llh) <= 1)
1320 GOTO(out_close, rc = 0);
1324 GOTO(out_close, rc = -ENOMEM);
1325 /* devname is only needed information to replace UUID records */
1327 strlcpy(mrd->target.mti_svname, devname,
1328 sizeof(mrd->target.mti_svname));
1329 /* data is parsed in llog callback */
1331 strlcpy(mrd->target.mti_params, data,
1332 sizeof(mrd->target.mti_params));
1333 /* Copy records to this temporary llog */
1334 mrd->temp_llh = orig_llh;
1336 rc = llog_process(env, backup_llh, replace_handler,
1340 rc2 = llog_close(NULL, backup_llh);
1344 rc2 = llog_close(NULL, orig_llh);
1350 CERROR("%s: llog should be restored: rc = %d\n",
1352 rc2 = llog_backup(env, mgs, ctxt, ctxt, backup,
1355 CERROR("%s: can't restore backup %s: rc = %d\n",
1356 mgs->obd_name, logname, rc2);
1360 OBD_FREE(backup, buf_size);
1363 llog_ctxt_put(ctxt);
1366 CERROR("%s: failed to replace log %s: rc = %d\n",
1367 mgs->obd_name, logname, rc);
1372 static int mgs_replace_nids_log(const struct lu_env *env,
1373 struct obd_device *obd,
1374 char *logname, char *devname, char *nids)
1376 CDEBUG(D_MGS, "Replace NIDs for %s in %s\n", devname, logname);
1377 return mgs_replace_log(env, obd, logname, devname,
1378 mgs_replace_nids_handler, nids);
1382 * Parse device name and get file system name and/or device index
1384 * @devname device name (ex. lustre-MDT0000)
1385 * @fsname file system name extracted from @devname and returned
1386 * to the caller (optional)
1387 * @index device index extracted from @devname and returned to
1388 * the caller (optional)
1390 * RETURN 0 success if we are only interested in
1391 * extracting fsname from devname.
1394 * LDD_F_SV_TYPE_* Besides extracting the fsname the
1395 * user also wants the index. Report to
1396 * the user the type of obd device the
1397 * returned index belongs too.
1399 * -EINVAL The obd device name is improper so
1400 * fsname could not be extracted.
1402 * -ENXIO Failed to extract the index out of
1403 * the obd device name. Most likely an
1404 * invalid obd device name
1406 static int mgs_parse_devname(char *devname, char *fsname, u32 *index)
1411 /* Extract fsname */
1413 rc = server_name2fsname(devname, fsname, NULL);
1415 CDEBUG(D_MGS, "Device name %s without fsname\n",
1422 rc = server_name2index(devname, index, NULL);
1424 CDEBUG(D_MGS, "Device name %s with wrong index\n",
1430 /* server_name2index can return LDD_F_SV_TYPE_* so always return rc */
1434 /* This is only called during replace_nids */
1435 static int only_mgs_is_running(struct obd_device *mgs_obd)
1437 /* TDB: Is global variable with devices count exists? */
1438 int num_devices = get_devices_count();
1439 int num_exports = 0;
1440 struct obd_export *exp;
1442 spin_lock(&mgs_obd->obd_dev_lock);
1443 list_for_each_entry(exp, &mgs_obd->obd_exports, exp_obd_chain) {
1444 /* skip self export */
1445 if (exp == mgs_obd->obd_self_export)
1447 if (exp_connect_flags(exp) & OBD_CONNECT_MDS_MDS)
1452 CERROR("%s: node %s still connected during replace_nids "
1453 "connect_flags:%llx\n",
1455 libcfs_nid2str(exp->exp_nid_stats->nid),
1456 exp_connect_flags(exp));
1459 spin_unlock(&mgs_obd->obd_dev_lock);
1461 /* osd, MGS and MGC + self_export
1462 (wc -l /proc/fs/lustre/devices <= 2) && (non self exports == 0) */
1463 return (num_devices <= 3) && (num_exports == 0);
1466 static int name_create_mdt(char **logname, char *fsname, int i)
1470 sprintf(mdt_index, "-MDT%04x", i);
1471 return name_create(logname, fsname, mdt_index);
1475 * Replace nids for \a device to \a nids values
1477 * \param obd MGS obd device
1478 * \param devname nids need to be replaced for this device
1479 * (ex. lustre-OST0000)
1480 * \param nids nids list (ex. nid1,nid2,nid3)
1484 int mgs_replace_nids(const struct lu_env *env,
1485 struct mgs_device *mgs,
1486 char *devname, char *nids)
1488 /* Assume fsname is part of device name */
1489 char fsname[MTI_NAME_MAXLEN];
1493 struct fs_db *fsdb = NULL;
1496 struct obd_device *mgs_obd = mgs->mgs_obd;
1499 /* We can only change NIDs if no other nodes are connected */
1500 spin_lock(&mgs_obd->obd_dev_lock);
1501 conn_state = mgs_obd->obd_no_conn;
1502 mgs_obd->obd_no_conn = 1;
1503 spin_unlock(&mgs_obd->obd_dev_lock);
1505 /* We can not change nids if not only MGS is started */
1506 if (!only_mgs_is_running(mgs_obd)) {
1507 CERROR("Only MGS is allowed to be started\n");
1508 GOTO(out, rc = -EINPROGRESS);
1511 /* Get fsname and index */
1512 rc = mgs_parse_devname(devname, fsname, &index);
1516 rc = mgs_find_or_make_fsdb(env, mgs, fsname, &fsdb);
1518 CERROR("%s: can't find fsdb: rc = %d\n", fsname, rc);
1522 /* Process client llogs */
1523 name_create(&logname, fsname, "-client");
1524 rc = mgs_replace_nids_log(env, mgs_obd, logname, devname, nids);
1525 name_destroy(&logname);
1527 CERROR("%s: error while replacing NIDs for %s: rc = %d\n",
1528 fsname, devname, rc);
1532 /* Process MDT llogs */
1533 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
1534 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
1536 name_create_mdt(&logname, fsname, i);
1537 rc = mgs_replace_nids_log(env, mgs_obd, logname, devname, nids);
1538 name_destroy(&logname);
1544 spin_lock(&mgs_obd->obd_dev_lock);
1545 mgs_obd->obd_no_conn = conn_state;
1546 spin_unlock(&mgs_obd->obd_dev_lock);
1549 mgs_put_fsdb(mgs, fsdb);
1555 * This is called for every record in llog. Some of records are
1556 * skipped, others are copied to new log as is.
1557 * Records to be skipped are
1558 * marker records marked SKIP
1559 * records enclosed between SKIP markers
1561 * \param[in] llh log to be processed
1562 * \param[in] rec current record
1563 * \param[in] data mgs_replace_data structure
1567 static int mgs_clear_config_handler(const struct lu_env *env,
1568 struct llog_handle *llh,
1569 struct llog_rec_hdr *rec, void *data)
1571 struct mgs_replace_data *mrd;
1572 struct lustre_cfg *lcfg = REC_DATA(rec);
1573 int cfg_len = REC_DATA_LEN(rec);
1578 mrd = (struct mgs_replace_data *)data;
1580 if (rec->lrh_type != OBD_CFG_REC) {
1581 CDEBUG(D_MGS, "Config llog Name=%s, Record Index=%u, "
1582 "Unhandled Record Type=%#x\n", llh->lgh_name,
1583 rec->lrh_index, rec->lrh_type);
1587 rc = lustre_cfg_sanity_check(lcfg, cfg_len);
1589 CDEBUG(D_MGS, "Config llog Name=%s, Invalid config file.",
1594 if (lcfg->lcfg_command == LCFG_MARKER) {
1595 struct cfg_marker *marker;
1597 marker = lustre_cfg_buf(lcfg, 1);
1598 if (marker->cm_flags & CM_SKIP) {
1599 if (marker->cm_flags & CM_START)
1601 if (marker->cm_flags & CM_END)
1603 /* SKIP section started or finished */
1604 CDEBUG(D_MGS, "Skip idx=%d, rc=%d, len=%d, "
1605 "cmd %x %s %s\n", rec->lrh_index, rc,
1606 rec->lrh_len, lcfg->lcfg_command,
1607 lustre_cfg_string(lcfg, 0),
1608 lustre_cfg_string(lcfg, 1));
1613 /* record enclosed between SKIP markers, skip it */
1614 CDEBUG(D_MGS, "Skip idx=%d, rc=%d, len=%d, "
1615 "cmd %x %s %s\n", rec->lrh_index, rc,
1616 rec->lrh_len, lcfg->lcfg_command,
1617 lustre_cfg_string(lcfg, 0),
1618 lustre_cfg_string(lcfg, 1));
1623 /* Record is placed in temporary llog as is */
1624 rc = llog_write(env, mrd->temp_llh, rec, LLOG_NEXT_IDX);
1626 CDEBUG(D_MGS, "Copied idx=%d, rc=%d, len=%d, cmd %x %s %s\n",
1627 rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
1628 lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
1633 * Directory CONFIGS/ may contain files which are not config logs to
1634 * be cleared. Skip any llogs with a non-alphanumeric character after
1635 * the last '-'. For example, fsname-MDT0000.sav, fsname-MDT0000.bak,
1636 * fsname-MDT0000.orig, fsname-MDT0000~, fsname-MDT0000.20150516, etc.
1638 static bool config_to_clear(const char *logname)
1643 str = strrchr(logname, '-');
1648 while (isalnum(str[++i]));
1649 return str[i] == '\0';
1653 * Clear config logs for \a name
1656 * \param mgs MGS device
1657 * \param name name of device or of filesystem
1658 * (ex. lustre-OST0000 or lustre) in later case all logs
1663 int mgs_clear_configs(const struct lu_env *env,
1664 struct mgs_device *mgs, const char *name)
1666 struct list_head dentry_list;
1667 struct mgs_direntry *dirent, *n;
1670 struct obd_device *mgs_obd = mgs->mgs_obd;
1675 /* Prevent clients and servers from connecting to mgs */
1676 spin_lock(&mgs_obd->obd_dev_lock);
1677 conn_state = mgs_obd->obd_no_conn;
1678 mgs_obd->obd_no_conn = 1;
1679 spin_unlock(&mgs_obd->obd_dev_lock);
1682 * config logs cannot be cleaned if anything other than
1685 if (!only_mgs_is_running(mgs_obd)) {
1686 CERROR("Only MGS is allowed to be started\n");
1687 GOTO(out, rc = -EBUSY);
1690 /* Find all the logs in the CONFIGS directory */
1691 rc = class_dentry_readdir(env, mgs, &dentry_list);
1693 CERROR("%s: cannot read config directory '%s': rc = %d\n",
1694 mgs_obd->obd_name, MOUNT_CONFIGS_DIR, rc);
1698 if (list_empty(&dentry_list)) {
1699 CERROR("%s: list empty reading config dir '%s': rc = %d\n",
1700 mgs_obd->obd_name, MOUNT_CONFIGS_DIR, -ENOENT);
1701 GOTO(out, rc = -ENOENT);
1704 OBD_ALLOC(namedash, strlen(name) + 2);
1705 if (namedash == NULL)
1706 GOTO(out, rc = -ENOMEM);
1707 snprintf(namedash, strlen(name) + 2, "%s-", name);
1709 list_for_each_entry(dirent, &dentry_list, mde_list) {
1710 if (strcmp(name, dirent->mde_name) &&
1711 strncmp(namedash, dirent->mde_name, strlen(namedash)))
1713 if (!config_to_clear(dirent->mde_name))
1715 CDEBUG(D_MGS, "%s: Clear config log %s\n",
1716 mgs_obd->obd_name, dirent->mde_name);
1717 rc = mgs_replace_log(env, mgs_obd, dirent->mde_name, NULL,
1718 mgs_clear_config_handler, NULL);
1723 list_for_each_entry_safe(dirent, n, &dentry_list, mde_list) {
1724 list_del_init(&dirent->mde_list);
1725 mgs_direntry_free(dirent);
1727 OBD_FREE(namedash, strlen(name) + 2);
1729 spin_lock(&mgs_obd->obd_dev_lock);
1730 mgs_obd->obd_no_conn = conn_state;
1731 spin_unlock(&mgs_obd->obd_dev_lock);
1736 static int record_lov_setup(const struct lu_env *env, struct llog_handle *llh,
1737 char *devname, struct lov_desc *desc)
1739 struct mgs_thread_info *mgi = mgs_env_info(env);
1740 struct llog_cfg_rec *lcr;
1743 lustre_cfg_bufs_reset(&mgi->mgi_bufs, devname);
1744 lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, desc, sizeof(*desc));
1745 lcr = lustre_cfg_rec_new(LCFG_SETUP, &mgi->mgi_bufs);
1749 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1750 lustre_cfg_rec_free(lcr);
1754 static int record_lmv_setup(const struct lu_env *env, struct llog_handle *llh,
1755 char *devname, struct lmv_desc *desc)
1757 struct mgs_thread_info *mgi = mgs_env_info(env);
1758 struct llog_cfg_rec *lcr;
1761 lustre_cfg_bufs_reset(&mgi->mgi_bufs, devname);
1762 lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, desc, sizeof(*desc));
1763 lcr = lustre_cfg_rec_new(LCFG_SETUP, &mgi->mgi_bufs);
1767 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1768 lustre_cfg_rec_free(lcr);
1772 static inline int record_mdc_add(const struct lu_env *env,
1773 struct llog_handle *llh,
1774 char *logname, char *mdcuuid,
1775 char *mdtuuid, char *index,
1778 return record_base(env,llh,logname,0,LCFG_ADD_MDC,
1779 mdtuuid,index,gen,mdcuuid);
1782 static inline int record_lov_add(const struct lu_env *env,
1783 struct llog_handle *llh,
1784 char *lov_name, char *ost_uuid,
1785 char *index, char *gen)
1787 return record_base(env, llh, lov_name, 0, LCFG_LOV_ADD_OBD,
1788 ost_uuid, index, gen, NULL);
1791 static inline int record_mount_opt(const struct lu_env *env,
1792 struct llog_handle *llh,
1793 char *profile, char *lov_name,
1796 return record_base(env, llh, NULL, 0, LCFG_MOUNTOPT,
1797 profile, lov_name, mdc_name, NULL);
1800 static int record_marker(const struct lu_env *env,
1801 struct llog_handle *llh,
1802 struct fs_db *fsdb, __u32 flags,
1803 char *tgtname, char *comment)
1805 struct mgs_thread_info *mgi = mgs_env_info(env);
1806 struct llog_cfg_rec *lcr;
1810 if (flags & CM_START)
1812 mgi->mgi_marker.cm_step = fsdb->fsdb_gen;
1813 mgi->mgi_marker.cm_flags = flags;
1814 mgi->mgi_marker.cm_vers = LUSTRE_VERSION_CODE;
1815 cplen = strlcpy(mgi->mgi_marker.cm_tgtname, tgtname,
1816 sizeof(mgi->mgi_marker.cm_tgtname));
1817 if (cplen >= sizeof(mgi->mgi_marker.cm_tgtname))
1819 cplen = strlcpy(mgi->mgi_marker.cm_comment, comment,
1820 sizeof(mgi->mgi_marker.cm_comment));
1821 if (cplen >= sizeof(mgi->mgi_marker.cm_comment))
1823 mgi->mgi_marker.cm_createtime = ktime_get_real_seconds();
1824 mgi->mgi_marker.cm_canceltime = 0;
1825 lustre_cfg_bufs_reset(&mgi->mgi_bufs, NULL);
1826 lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, &mgi->mgi_marker,
1827 sizeof(mgi->mgi_marker));
1828 lcr = lustre_cfg_rec_new(LCFG_MARKER, &mgi->mgi_bufs);
1832 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1833 lustre_cfg_rec_free(lcr);
1837 static int record_start_log(const struct lu_env *env, struct mgs_device *mgs,
1838 struct llog_handle **llh, char *name)
1840 static struct obd_uuid cfg_uuid = { .uuid = "config_uuid" };
1841 struct llog_ctxt *ctxt;
1846 GOTO(out, rc = -EBUSY);
1848 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
1850 GOTO(out, rc = -ENODEV);
1851 LASSERT(ctxt->loc_obd == mgs->mgs_obd);
1853 rc = llog_open_create(env, ctxt, llh, NULL, name);
1856 rc = llog_init_handle(env, *llh, LLOG_F_IS_PLAIN, &cfg_uuid);
1858 llog_close(env, *llh);
1860 llog_ctxt_put(ctxt);
1863 CERROR("%s: can't start log %s: rc = %d\n",
1864 mgs->mgs_obd->obd_name, name, rc);
1870 static int record_end_log(const struct lu_env *env, struct llog_handle **llh)
1874 rc = llog_close(env, *llh);
1880 /******************** config "macros" *********************/
1882 /* write an lcfg directly into a log (with markers) */
1883 static int mgs_write_log_direct(const struct lu_env *env,
1884 struct mgs_device *mgs, struct fs_db *fsdb,
1885 char *logname, struct llog_cfg_rec *lcr,
1886 char *devname, char *comment)
1888 struct llog_handle *llh = NULL;
1893 rc = record_start_log(env, mgs, &llh, logname);
1897 /* FIXME These should be a single journal transaction */
1898 rc = record_marker(env, llh, fsdb, CM_START, devname, comment);
1901 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1904 rc = record_marker(env, llh, fsdb, CM_END, devname, comment);
1908 record_end_log(env, &llh);
1912 /* write the lcfg in all logs for the given fs */
1913 static int mgs_write_log_direct_all(const struct lu_env *env,
1914 struct mgs_device *mgs,
1916 struct mgs_target_info *mti,
1917 struct llog_cfg_rec *lcr, char *devname,
1918 char *comment, int server_only)
1920 struct list_head log_list;
1921 struct mgs_direntry *dirent, *n;
1922 char *fsname = mti->mti_fsname;
1923 int rc = 0, len = strlen(fsname);
1926 /* Find all the logs in the CONFIGS directory */
1927 rc = class_dentry_readdir(env, mgs, &log_list);
1931 /* Could use fsdb index maps instead of directory listing */
1932 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
1933 list_del_init(&dirent->mde_list);
1934 /* don't write to sptlrpc rule log */
1935 if (strstr(dirent->mde_name, "-sptlrpc") != NULL)
1938 /* caller wants write server logs only */
1939 if (server_only && strstr(dirent->mde_name, "-client") != NULL)
1942 if (strlen(dirent->mde_name) <= len ||
1943 strncmp(fsname, dirent->mde_name, len) != 0 ||
1944 dirent->mde_name[len] != '-')
1947 CDEBUG(D_MGS, "Changing log %s\n", dirent->mde_name);
1948 /* Erase any old settings of this same parameter */
1949 rc = mgs_modify(env, mgs, fsdb, mti, dirent->mde_name,
1950 devname, comment, CM_SKIP);
1952 CERROR("%s: Can't modify llog %s: rc = %d\n",
1953 mgs->mgs_obd->obd_name, dirent->mde_name, rc);
1956 /* Write the new one */
1957 rc = mgs_write_log_direct(env, mgs, fsdb, dirent->mde_name,
1958 lcr, devname, comment);
1960 CERROR("%s: writing log %s: rc = %d\n",
1961 mgs->mgs_obd->obd_name, dirent->mde_name, rc);
1963 mgs_direntry_free(dirent);
1969 static int mgs_write_log_osp_to_mdt(const struct lu_env *env,
1970 struct mgs_device *mgs,
1972 struct mgs_target_info *mti,
1973 int index, char *logname);
1974 static int mgs_write_log_osc_to_lov(const struct lu_env *env,
1975 struct mgs_device *mgs,
1977 struct mgs_target_info *mti,
1978 char *logname, char *suffix, char *lovname,
1979 enum lustre_sec_part sec_part, int flags);
1980 static int name_create_mdt_and_lov(char **logname, char **lovname,
1981 struct fs_db *fsdb, int i);
1983 static int add_param(char *params, char *key, char *val)
1985 char *start = params + strlen(params);
1986 char *end = params + sizeof(((struct mgs_target_info *)0)->mti_params);
1990 keylen = strlen(key);
1991 if (start + 1 + keylen + strlen(val) >= end) {
1992 CERROR("params are too long: %s %s%s\n",
1993 params, key != NULL ? key : "", val);
1997 sprintf(start, " %s%s", key != NULL ? key : "", val);
2002 * Walk through client config log record and convert the related records
2005 static int mgs_steal_client_llog_handler(const struct lu_env *env,
2006 struct llog_handle *llh,
2007 struct llog_rec_hdr *rec, void *data)
2009 struct mgs_device *mgs;
2010 struct obd_device *obd;
2011 struct mgs_target_info *mti, *tmti;
2013 int cfg_len = rec->lrh_len;
2014 char *cfg_buf = (char*) (rec + 1);
2015 struct lustre_cfg *lcfg;
2017 struct llog_handle *mdt_llh = NULL;
2018 static int got_an_osc_or_mdc = 0;
2019 /* 0: not found any osc/mdc;
2023 static int last_step = -1;
2028 mti = ((struct temp_comp*)data)->comp_mti;
2029 tmti = ((struct temp_comp*)data)->comp_tmti;
2030 fsdb = ((struct temp_comp*)data)->comp_fsdb;
2031 obd = ((struct temp_comp *)data)->comp_obd;
2032 mgs = lu2mgs_dev(obd->obd_lu_dev);
2035 if (rec->lrh_type != OBD_CFG_REC) {
2036 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
2040 rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
2042 CERROR("Insane cfg\n");
2046 lcfg = (struct lustre_cfg *)cfg_buf;
2048 if (lcfg->lcfg_command == LCFG_MARKER) {
2049 struct cfg_marker *marker;
2050 marker = lustre_cfg_buf(lcfg, 1);
2051 if (!strncmp(marker->cm_comment, "add osc", 7) &&
2052 (marker->cm_flags & CM_START) &&
2053 !(marker->cm_flags & CM_SKIP)) {
2054 got_an_osc_or_mdc = 1;
2055 cplen = strlcpy(tmti->mti_svname, marker->cm_tgtname,
2056 sizeof(tmti->mti_svname));
2057 if (cplen >= sizeof(tmti->mti_svname))
2059 rc = record_start_log(env, mgs, &mdt_llh,
2063 rc = record_marker(env, mdt_llh, fsdb, CM_START,
2064 mti->mti_svname, "add osc(copied)");
2065 record_end_log(env, &mdt_llh);
2066 last_step = marker->cm_step;
2069 if (!strncmp(marker->cm_comment, "add osc", 7) &&
2070 (marker->cm_flags & CM_END) &&
2071 !(marker->cm_flags & CM_SKIP)) {
2072 LASSERT(last_step == marker->cm_step);
2074 got_an_osc_or_mdc = 0;
2075 memset(tmti, 0, sizeof(*tmti));
2076 rc = record_start_log(env, mgs, &mdt_llh,
2080 rc = record_marker(env, mdt_llh, fsdb, CM_END,
2081 mti->mti_svname, "add osc(copied)");
2082 record_end_log(env, &mdt_llh);
2085 if (!strncmp(marker->cm_comment, "add mdc", 7) &&
2086 (marker->cm_flags & CM_START) &&
2087 !(marker->cm_flags & CM_SKIP)) {
2088 got_an_osc_or_mdc = 2;
2089 last_step = marker->cm_step;
2090 memcpy(tmti->mti_svname, marker->cm_tgtname,
2091 strlen(marker->cm_tgtname));
2095 if (!strncmp(marker->cm_comment, "add mdc", 7) &&
2096 (marker->cm_flags & CM_END) &&
2097 !(marker->cm_flags & CM_SKIP)) {
2098 LASSERT(last_step == marker->cm_step);
2100 got_an_osc_or_mdc = 0;
2101 memset(tmti, 0, sizeof(*tmti));
2106 if (got_an_osc_or_mdc == 0 || last_step < 0)
2109 if (lcfg->lcfg_command == LCFG_ADD_UUID) {
2110 __u64 nodenid = lcfg->lcfg_nid;
2112 if (strlen(tmti->mti_uuid) == 0) {
2113 /* target uuid not set, this config record is before
2114 * LCFG_SETUP, this nid is one of target node nid.
2116 tmti->mti_nids[tmti->mti_nid_count] = nodenid;
2117 tmti->mti_nid_count++;
2119 char nidstr[LNET_NIDSTR_SIZE];
2121 /* failover node nid */
2122 libcfs_nid2str_r(nodenid, nidstr, sizeof(nidstr));
2123 rc = add_param(tmti->mti_params, PARAM_FAILNODE,
2130 if (lcfg->lcfg_command == LCFG_SETUP) {
2133 target = lustre_cfg_string(lcfg, 1);
2134 memcpy(tmti->mti_uuid, target, strlen(target));
2138 /* ignore client side sptlrpc_conf_log */
2139 if (lcfg->lcfg_command == LCFG_SPTLRPC_CONF)
2142 if (lcfg->lcfg_command == LCFG_ADD_MDC &&
2143 strstr(lustre_cfg_string(lcfg, 0), "-clilmv") != NULL) {
2146 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1)
2149 memcpy(tmti->mti_fsname, mti->mti_fsname,
2150 strlen(mti->mti_fsname));
2151 tmti->mti_stripe_index = index;
2153 rc = mgs_write_log_osp_to_mdt(env, mgs, fsdb, tmti,
2154 mti->mti_stripe_index,
2156 memset(tmti, 0, sizeof(*tmti));
2160 if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD) {
2163 char *logname, *lovname;
2165 rc = name_create_mdt_and_lov(&logname, &lovname, fsdb,
2166 mti->mti_stripe_index);
2169 sprintf(mdt_index, "-MDT%04x", mti->mti_stripe_index);
2171 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1) {
2172 name_destroy(&logname);
2173 name_destroy(&lovname);
2177 tmti->mti_stripe_index = index;
2178 rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, tmti, logname,
2181 name_destroy(&logname);
2182 name_destroy(&lovname);
2188 /* fsdb->fsdb_mutex is already held in mgs_write_log_target*/
2189 /* stealed from mgs_get_fsdb_from_llog*/
2190 static int mgs_steal_llog_for_mdt_from_client(const struct lu_env *env,
2191 struct mgs_device *mgs,
2193 struct temp_comp* comp)
2195 struct llog_handle *loghandle;
2196 struct mgs_target_info *tmti;
2197 struct llog_ctxt *ctxt;
2202 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
2203 LASSERT(ctxt != NULL);
2205 OBD_ALLOC_PTR(tmti);
2207 GOTO(out_ctxt, rc = -ENOMEM);
2209 comp->comp_tmti = tmti;
2210 comp->comp_obd = mgs->mgs_obd;
2212 rc = llog_open(env, ctxt, &loghandle, NULL, client_name,
2220 rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
2222 GOTO(out_close, rc);
2224 rc = llog_process_or_fork(env, loghandle, mgs_steal_client_llog_handler,
2225 (void *)comp, NULL, false);
2226 CDEBUG(D_MGS, "steal llog re = %d\n", rc);
2228 llog_close(env, loghandle);
2232 llog_ctxt_put(ctxt);
2236 /* lmv is the second thing for client logs */
2237 /* copied from mgs_write_log_lov. Please refer to that. */
2238 static int mgs_write_log_lmv(const struct lu_env *env,
2239 struct mgs_device *mgs,
2241 struct mgs_target_info *mti,
2242 char *logname, char *lmvname)
2244 struct llog_handle *llh = NULL;
2245 struct lmv_desc *lmvdesc;
2250 CDEBUG(D_MGS, "Writing lmv(%s) log for %s\n", lmvname,logname);
2252 OBD_ALLOC_PTR(lmvdesc);
2253 if (lmvdesc == NULL)
2255 lmvdesc->ld_active_tgt_count = 0;
2256 lmvdesc->ld_tgt_count = 0;
2257 sprintf((char*)lmvdesc->ld_uuid.uuid, "%s_UUID", lmvname);
2258 uuid = (char *)lmvdesc->ld_uuid.uuid;
2260 rc = record_start_log(env, mgs, &llh, logname);
2263 rc = record_marker(env, llh, fsdb, CM_START, lmvname, "lmv setup");
2266 rc = record_attach(env, llh, lmvname, "lmv", uuid);
2269 rc = record_lmv_setup(env, llh, lmvname, lmvdesc);
2272 rc = record_marker(env, llh, fsdb, CM_END, lmvname, "lmv setup");
2276 record_end_log(env, &llh);
2278 OBD_FREE_PTR(lmvdesc);
2282 /* lov is the first thing in the mdt and client logs */
2283 static int mgs_write_log_lov(const struct lu_env *env, struct mgs_device *mgs,
2284 struct fs_db *fsdb, struct mgs_target_info *mti,
2285 char *logname, char *lovname)
2287 struct llog_handle *llh = NULL;
2288 struct lov_desc *lovdesc;
2293 CDEBUG(D_MGS, "Writing lov(%s) log for %s\n", lovname, logname);
2296 #01 L attach 0:lov_mdsA 1:lov 2:71ccb_lov_mdsA_19f961a9e1
2297 #02 L lov_setup 0:lov_mdsA 1:(struct lov_desc)
2298 uuid=lov1_UUID, stripe count=1, size=1048576, offset=0, pattern=0
2301 /* FIXME just make lov_setup accept empty desc (put uuid in buf 2) */
2302 OBD_ALLOC_PTR(lovdesc);
2303 if (lovdesc == NULL)
2305 lovdesc->ld_magic = LOV_DESC_MAGIC;
2306 lovdesc->ld_tgt_count = 0;
2307 /* Defaults. Can be changed later by lcfg config_param */
2308 lovdesc->ld_default_stripe_count = 1;
2309 lovdesc->ld_pattern = LOV_PATTERN_RAID0;
2310 lovdesc->ld_default_stripe_size = LOV_DESC_STRIPE_SIZE_DEFAULT;
2311 lovdesc->ld_default_stripe_offset = -1;
2312 lovdesc->ld_qos_maxage = LOV_DESC_QOS_MAXAGE_DEFAULT;
2313 sprintf((char*)lovdesc->ld_uuid.uuid, "%s_UUID", lovname);
2314 /* can these be the same? */
2315 uuid = (char *)lovdesc->ld_uuid.uuid;
2317 /* This should always be the first entry in a log.
2318 rc = mgs_clear_log(obd, logname); */
2319 rc = record_start_log(env, mgs, &llh, logname);
2322 /* FIXME these should be a single journal transaction */
2323 rc = record_marker(env, llh, fsdb, CM_START, lovname, "lov setup");
2326 rc = record_attach(env, llh, lovname, "lov", uuid);
2329 rc = record_lov_setup(env, llh, lovname, lovdesc);
2332 rc = record_marker(env, llh, fsdb, CM_END, lovname, "lov setup");
2337 record_end_log(env, &llh);
2339 OBD_FREE_PTR(lovdesc);
2343 /* add failnids to open log */
2344 static int mgs_write_log_failnids(const struct lu_env *env,
2345 struct mgs_target_info *mti,
2346 struct llog_handle *llh,
2349 char *failnodeuuid = NULL;
2350 char *ptr = mti->mti_params;
2355 #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) nal=90 0: 1:uml1_UUID
2356 #04 L add_uuid nid=1@elan(0x1000000000001) nal=90 0: 1:uml1_UUID
2357 #05 L setup 0:OSC_uml1_ost1_mdsA 1:ost1_UUID 2:uml1_UUID
2358 #06 L add_uuid nid=uml2@tcp(0x20000c0a80202) nal=90 0: 1:uml2_UUID
2359 #0x L add_uuid nid=2@elan(0x1000000000002) nal=90 0: 1:uml2_UUID
2360 #07 L add_conn 0:OSC_uml1_ost1_mdsA 1:uml2_UUID
2364 * Pull failnid info out of params string, which may contain something
2365 * like "<nid1>,<nid2>:<nid3>,<nid4>". class_parse_nid() does not
2366 * complain about abnormal inputs like ",:<nid1>", "<nid1>:,<nid2>",
2367 * etc. However, convert_hostnames() should have caught those.
2369 while (class_find_param(ptr, PARAM_FAILNODE, &ptr) == 0) {
2370 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
2371 char nidstr[LNET_NIDSTR_SIZE];
2373 if (failnodeuuid == NULL) {
2374 /* We don't know the failover node name,
2375 * so just use the first nid as the uuid */
2376 libcfs_nid2str_r(nid, nidstr, sizeof(nidstr));
2377 rc = name_create(&failnodeuuid, nidstr, "");
2381 CDEBUG(D_MGS, "add nid %s for failover uuid %s, "
2383 libcfs_nid2str_r(nid, nidstr, sizeof(nidstr)),
2384 failnodeuuid, cliname);
2385 rc = record_add_uuid(env, llh, nid, failnodeuuid);
2387 * If *ptr is ':', we have added all NIDs for
2391 rc = record_add_conn(env, llh, cliname,
2393 name_destroy(&failnodeuuid);
2394 failnodeuuid = NULL;
2398 rc = record_add_conn(env, llh, cliname, failnodeuuid);
2399 name_destroy(&failnodeuuid);
2400 failnodeuuid = NULL;
2407 static int mgs_write_log_mdc_to_lmv(const struct lu_env *env,
2408 struct mgs_device *mgs,
2410 struct mgs_target_info *mti,
2411 char *logname, char *lmvname)
2413 struct llog_handle *llh = NULL;
2414 char *mdcname = NULL;
2415 char *nodeuuid = NULL;
2416 char *mdcuuid = NULL;
2417 char *lmvuuid = NULL;
2419 char nidstr[LNET_NIDSTR_SIZE];
2423 if (mgs_log_is_empty(env, mgs, logname)) {
2424 CERROR("log is empty! Logical error\n");
2428 CDEBUG(D_MGS, "adding mdc for %s to log %s:lmv(%s)\n",
2429 mti->mti_svname, logname, lmvname);
2431 libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2432 rc = name_create(&nodeuuid, nidstr, "");
2435 rc = name_create(&mdcname, mti->mti_svname, "-mdc");
2438 rc = name_create(&mdcuuid, mdcname, "_UUID");
2441 rc = name_create(&lmvuuid, lmvname, "_UUID");
2445 rc = record_start_log(env, mgs, &llh, logname);
2448 rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
2452 for (i = 0; i < mti->mti_nid_count; i++) {
2453 CDEBUG(D_MGS, "add nid %s for mdt\n",
2454 libcfs_nid2str_r(mti->mti_nids[i],
2455 nidstr, sizeof(nidstr)));
2457 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2462 rc = record_attach(env, llh, mdcname, LUSTRE_MDC_NAME, lmvuuid);
2465 rc = record_setup(env, llh, mdcname, mti->mti_uuid, nodeuuid,
2469 rc = mgs_write_log_failnids(env, mti, llh, mdcname);
2472 snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
2473 rc = record_mdc_add(env, llh, lmvname, mdcuuid, mti->mti_uuid,
2477 rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname,
2482 record_end_log(env, &llh);
2484 name_destroy(&lmvuuid);
2485 name_destroy(&mdcuuid);
2486 name_destroy(&mdcname);
2487 name_destroy(&nodeuuid);
2491 static inline int name_create_lov(char **lovname, char *mdtname,
2492 struct fs_db *fsdb, int index)
2495 if (index == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2496 return name_create(lovname, fsdb->fsdb_name, "-mdtlov");
2498 return name_create(lovname, mdtname, "-mdtlov");
2501 static int name_create_mdt_and_lov(char **logname, char **lovname,
2502 struct fs_db *fsdb, int i)
2506 rc = name_create_mdt(logname, fsdb->fsdb_name, i);
2510 if (i == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2511 rc = name_create(lovname, fsdb->fsdb_name, "-mdtlov");
2513 rc = name_create(lovname, *logname, "-mdtlov");
2515 name_destroy(logname);
2521 static inline int name_create_mdt_osc(char **oscname, char *ostname,
2522 struct fs_db *fsdb, int i)
2526 if (i == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2527 sprintf(suffix, "-osc");
2529 sprintf(suffix, "-osc-MDT%04x", i);
2530 return name_create(oscname, ostname, suffix);
2533 /* add new mdc to already existent MDS */
2534 static int mgs_write_log_osp_to_mdt(const struct lu_env *env,
2535 struct mgs_device *mgs,
2537 struct mgs_target_info *mti,
2538 int mdt_index, char *logname)
2540 struct llog_handle *llh = NULL;
2541 char *nodeuuid = NULL;
2542 char *ospname = NULL;
2543 char *lovuuid = NULL;
2544 char *mdtuuid = NULL;
2545 char *svname = NULL;
2546 char *mdtname = NULL;
2547 char *lovname = NULL;
2549 char nidstr[LNET_NIDSTR_SIZE];
2553 if (mgs_log_is_empty(env, mgs, mti->mti_svname)) {
2554 CERROR("log is empty! Logical error\n");
2558 CDEBUG(D_MGS, "adding osp index %d to %s\n", mti->mti_stripe_index,
2561 rc = name_create_mdt(&mdtname, fsdb->fsdb_name, mti->mti_stripe_index);
2565 libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2566 rc = name_create(&nodeuuid, nidstr, "");
2568 GOTO(out_destory, rc);
2570 rc = name_create(&svname, mdtname, "-osp");
2572 GOTO(out_destory, rc);
2574 sprintf(index_str, "-MDT%04x", mdt_index);
2575 rc = name_create(&ospname, svname, index_str);
2577 GOTO(out_destory, rc);
2579 rc = name_create_lov(&lovname, logname, fsdb, mdt_index);
2581 GOTO(out_destory, rc);
2583 rc = name_create(&lovuuid, lovname, "_UUID");
2585 GOTO(out_destory, rc);
2587 rc = name_create(&mdtuuid, mdtname, "_UUID");
2589 GOTO(out_destory, rc);
2591 rc = record_start_log(env, mgs, &llh, logname);
2593 GOTO(out_destory, rc);
2595 rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
2598 GOTO(out_destory, rc);
2600 for (i = 0; i < mti->mti_nid_count; i++) {
2601 CDEBUG(D_MGS, "add nid %s for mdt\n",
2602 libcfs_nid2str_r(mti->mti_nids[i],
2603 nidstr, sizeof(nidstr)));
2604 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2609 rc = record_attach(env, llh, ospname, LUSTRE_OSP_NAME, lovuuid);
2613 rc = record_setup(env, llh, ospname, mti->mti_uuid, nodeuuid,
2618 rc = mgs_write_log_failnids(env, mti, llh, ospname);
2622 /* Add mdc(osp) to lod */
2623 snprintf(index_str, sizeof(index_str), "%d", mti->mti_stripe_index);
2624 rc = record_base(env, llh, lovname, 0, LCFG_ADD_MDC, mti->mti_uuid,
2625 index_str, "1", NULL);
2629 rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname, "add osp");
2634 record_end_log(env, &llh);
2637 name_destroy(&mdtuuid);
2638 name_destroy(&lovuuid);
2639 name_destroy(&lovname);
2640 name_destroy(&ospname);
2641 name_destroy(&svname);
2642 name_destroy(&nodeuuid);
2643 name_destroy(&mdtname);
2647 static int mgs_write_log_mdt0(const struct lu_env *env,
2648 struct mgs_device *mgs,
2650 struct mgs_target_info *mti)
2652 char *log = mti->mti_svname;
2653 struct llog_handle *llh = NULL;
2654 char *uuid, *lovname;
2656 char *ptr = mti->mti_params;
2657 int rc = 0, failout = 0;
2660 OBD_ALLOC(uuid, sizeof(struct obd_uuid));
2664 if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
2665 failout = (strncmp(ptr, "failout", 7) == 0);
2667 rc = name_create(&lovname, log, "-mdtlov");
2670 if (mgs_log_is_empty(env, mgs, log)) {
2671 rc = mgs_write_log_lov(env, mgs, fsdb, mti, log, lovname);
2676 sprintf(mdt_index, "%d", mti->mti_stripe_index);
2678 rc = record_start_log(env, mgs, &llh, log);
2682 /* add MDT itself */
2684 /* FIXME this whole fn should be a single journal transaction */
2685 sprintf(uuid, "%s_UUID", log);
2686 rc = record_marker(env, llh, fsdb, CM_START, log, "add mdt");
2689 rc = record_attach(env, llh, log, LUSTRE_MDT_NAME, uuid);
2692 rc = record_mount_opt(env, llh, log, lovname, NULL);
2695 rc = record_setup(env, llh, log, uuid, mdt_index, lovname,
2696 failout ? "n" : "f");
2699 rc = record_marker(env, llh, fsdb, CM_END, log, "add mdt");
2703 record_end_log(env, &llh);
2705 name_destroy(&lovname);
2707 OBD_FREE(uuid, sizeof(struct obd_uuid));
2711 /* envelope method for all layers log */
2712 static int mgs_write_log_mdt(const struct lu_env *env,
2713 struct mgs_device *mgs,
2715 struct mgs_target_info *mti)
2717 struct mgs_thread_info *mgi = mgs_env_info(env);
2718 struct llog_handle *llh = NULL;
2723 CDEBUG(D_MGS, "writing new mdt %s\n", mti->mti_svname);
2725 if (mti->mti_uuid[0] == '\0') {
2726 /* Make up our own uuid */
2727 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
2728 "%s_UUID", mti->mti_svname);
2732 rc = mgs_write_log_mdt0(env, mgs, fsdb, mti);
2735 /* Append the mdt info to the client log */
2736 rc = name_create(&cliname, mti->mti_fsname, "-client");
2740 if (mgs_log_is_empty(env, mgs, cliname)) {
2741 /* Start client log */
2742 rc = mgs_write_log_lov(env, mgs, fsdb, mti, cliname,
2746 rc = mgs_write_log_lmv(env, mgs, fsdb, mti, cliname,
2753 #09 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0: 1:uml1_UUID
2754 #10 L attach 0:MDC_uml1_mdsA_MNT_client 1:mdc 2:1d834_MNT_client_03f
2755 #11 L setup 0:MDC_uml1_mdsA_MNT_client 1:mdsA_UUID 2:uml1_UUID
2756 #12 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0: 1:uml2_UUID
2757 #13 L add_conn 0:MDC_uml1_mdsA_MNT_client 1:uml2_UUID
2758 #14 L mount_option 0: 1:client 2:lov1 3:MDC_uml1_mdsA_MNT_client
2761 /* copy client info about lov/lmv */
2762 mgi->mgi_comp.comp_mti = mti;
2763 mgi->mgi_comp.comp_fsdb = fsdb;
2765 rc = mgs_steal_llog_for_mdt_from_client(env, mgs, cliname,
2769 rc = mgs_write_log_mdc_to_lmv(env, mgs, fsdb, mti, cliname,
2775 rc = record_start_log(env, mgs, &llh, cliname);
2779 rc = record_marker(env, llh, fsdb, CM_START, cliname, "mount opts");
2782 rc = record_mount_opt(env, llh, cliname, fsdb->fsdb_clilov,
2786 rc = record_marker(env, llh, fsdb, CM_END, cliname, "mount opts");
2790 /* for_all_existing_mdt except current one */
2791 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
2792 if (i != mti->mti_stripe_index &&
2793 test_bit(i, fsdb->fsdb_mdt_index_map)) {
2796 rc = name_create_mdt(&logname, fsdb->fsdb_name, i);
2800 /* NB: If the log for the MDT is empty, it means
2801 * the MDT is only added to the index
2802 * map, and not being process yet, i.e. this
2803 * is an unregistered MDT, see mgs_write_log_target().
2804 * so we should skip it. Otherwise
2806 * 1. MGS get register request for MDT1 and MDT2.
2808 * 2. Then both MDT1 and MDT2 are added into
2809 * fsdb_mdt_index_map. (see mgs_set_index()).
2811 * 3. Then MDT1 get the lock of fsdb_mutex, then
2812 * generate the config log, here, it will regard MDT2
2813 * as an existent MDT, and generate "add osp" for
2814 * lustre-MDT0001-osp-MDT0002. Note: at the moment
2815 * MDT0002 config log is still empty, so it will
2816 * add "add osp" even before "lov setup", which
2817 * will definitly cause trouble.
2819 * 4. MDT1 registeration finished, fsdb_mutex is
2820 * released, then MDT2 get in, then in above
2821 * mgs_steal_llog_for_mdt_from_client(), it will
2822 * add another osp log for lustre-MDT0001-osp-MDT0002,
2823 * which will cause another trouble.*/
2824 if (!mgs_log_is_empty(env, mgs, logname))
2825 rc = mgs_write_log_osp_to_mdt(env, mgs, fsdb,
2828 name_destroy(&logname);
2834 record_end_log(env, &llh);
2836 name_destroy(&cliname);
2840 /* Add the ost info to the client/mdt lov */
2841 static int mgs_write_log_osc_to_lov(const struct lu_env *env,
2842 struct mgs_device *mgs, struct fs_db *fsdb,
2843 struct mgs_target_info *mti,
2844 char *logname, char *suffix, char *lovname,
2845 enum lustre_sec_part sec_part, int flags)
2847 struct llog_handle *llh = NULL;
2848 char *nodeuuid = NULL;
2849 char *oscname = NULL;
2850 char *oscuuid = NULL;
2851 char *lovuuid = NULL;
2852 char *svname = NULL;
2854 char nidstr[LNET_NIDSTR_SIZE];
2858 CDEBUG(D_INFO, "adding osc for %s to log %s\n",
2859 mti->mti_svname, logname);
2861 if (mgs_log_is_empty(env, mgs, logname)) {
2862 CERROR("log is empty! Logical error\n");
2866 libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2867 rc = name_create(&nodeuuid, nidstr, "");
2870 rc = name_create(&svname, mti->mti_svname, "-osc");
2874 /* for the system upgraded from old 1.8, keep using the old osc naming
2875 * style for mdt, see name_create_mdt_osc(). LU-1257 */
2876 if (test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2877 rc = name_create(&oscname, svname, "");
2879 rc = name_create(&oscname, svname, suffix);
2883 rc = name_create(&oscuuid, oscname, "_UUID");
2886 rc = name_create(&lovuuid, lovname, "_UUID");
2892 #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0: 1:uml1_UUID
2894 #04 L add_uuid nid=1@elan(0x1000000000001) nal=90 0: 1:uml1_UUID
2895 #04 L attach 0:OSC_uml1_ost1_MNT_client 1:osc 2:89070_lov1_a41dff51a
2896 #05 L setup 0:OSC_uml1_ost1_MNT_client 1:ost1_UUID 2:uml1_UUID
2898 #06 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0: 1:uml2_UUID
2899 #07 L add_conn 0:OSC_uml1_ost1_MNT_client 1:uml2_UUID
2900 #08 L lov_modify_tgts add 0:lov1 1:ost1_UUID 2(index):0 3(gen):1
2903 rc = record_start_log(env, mgs, &llh, logname);
2907 /* FIXME these should be a single journal transaction */
2908 rc = record_marker(env, llh, fsdb, CM_START | flags, mti->mti_svname,
2913 /* NB: don't change record order, because upon MDT steal OSC config
2914 * from client, it treats all nids before LCFG_SETUP as target nids
2915 * (multiple interfaces), while nids after as failover node nids.
2916 * See mgs_steal_client_llog_handler() LCFG_ADD_UUID.
2918 for (i = 0; i < mti->mti_nid_count; i++) {
2919 CDEBUG(D_MGS, "add nid %s\n",
2920 libcfs_nid2str_r(mti->mti_nids[i],
2921 nidstr, sizeof(nidstr)));
2922 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2926 rc = record_attach(env, llh, oscname, LUSTRE_OSC_NAME, lovuuid);
2929 rc = record_setup(env, llh, oscname, mti->mti_uuid, nodeuuid,
2933 rc = mgs_write_log_failnids(env, mti, llh, oscname);
2937 snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
2939 rc = record_lov_add(env, llh, lovname, mti->mti_uuid, index, "1");
2942 rc = record_marker(env, llh, fsdb, CM_END | flags, mti->mti_svname,
2947 record_end_log(env, &llh);
2949 name_destroy(&lovuuid);
2950 name_destroy(&oscuuid);
2951 name_destroy(&oscname);
2952 name_destroy(&svname);
2953 name_destroy(&nodeuuid);
2957 static int mgs_write_log_ost(const struct lu_env *env,
2958 struct mgs_device *mgs, struct fs_db *fsdb,
2959 struct mgs_target_info *mti)
2961 struct llog_handle *llh = NULL;
2962 char *logname, *lovname;
2963 char *ptr = mti->mti_params;
2964 int rc, flags = 0, failout = 0, i;
2967 CDEBUG(D_MGS, "writing new ost %s\n", mti->mti_svname);
2969 /* The ost startup log */
2971 /* If the ost log already exists, that means that someone reformatted
2972 the ost and it called target_add again. */
2973 if (!mgs_log_is_empty(env, mgs, mti->mti_svname)) {
2974 LCONSOLE_ERROR_MSG(0x141, "The config log for %s already "
2975 "exists, yet the server claims it never "
2976 "registered. It may have been reformatted, "
2977 "or the index changed. writeconf the MDT to "
2978 "regenerate all logs.\n", mti->mti_svname);
2983 attach obdfilter ost1 ost1_UUID
2984 setup /dev/loop2 ldiskfs f|n errors=remount-ro,user_xattr
2986 if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
2987 failout = (strncmp(ptr, "failout", 7) == 0);
2988 rc = record_start_log(env, mgs, &llh, mti->mti_svname);
2991 /* FIXME these should be a single journal transaction */
2992 rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,"add ost");
2995 if (*mti->mti_uuid == '\0')
2996 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
2997 "%s_UUID", mti->mti_svname);
2998 rc = record_attach(env, llh, mti->mti_svname,
2999 "obdfilter"/*LUSTRE_OST_NAME*/, mti->mti_uuid);
3002 rc = record_setup(env, llh, mti->mti_svname,
3003 "dev"/*ignored*/, "type"/*ignored*/,
3004 failout ? "n" : "f", NULL/*options*/);
3007 rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname, "add ost");
3011 record_end_log(env, &llh);
3014 /* We also have to update the other logs where this osc is part of
3017 if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
3018 /* If we're upgrading, the old mdt log already has our
3019 entry. Let's do a fake one for fun. */
3020 /* Note that we can't add any new failnids, since we don't
3021 know the old osc names. */
3022 flags = CM_SKIP | CM_UPGRADE146;
3024 } else if ((mti->mti_flags & LDD_F_UPDATE) != LDD_F_UPDATE) {
3025 /* If the update flag isn't set, don't update client/mdt
3028 LCONSOLE_WARN("Client log for %s was not updated; writeconf "
3029 "the MDT first to regenerate it.\n",
3033 /* Add ost to all MDT lov defs */
3034 for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
3035 if (test_bit(i, fsdb->fsdb_mdt_index_map)) {
3038 rc = name_create_mdt_and_lov(&logname, &lovname, fsdb,
3043 snprintf(mdt_index, sizeof(mdt_index), "-MDT%04x", i);
3044 rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, mti,
3046 lovname, LUSTRE_SP_MDT,
3048 name_destroy(&logname);
3049 name_destroy(&lovname);
3055 /* Append ost info to the client log */
3056 rc = name_create(&logname, mti->mti_fsname, "-client");
3059 if (mgs_log_is_empty(env, mgs, logname)) {
3060 /* Start client log */
3061 rc = mgs_write_log_lov(env, mgs, fsdb, mti, logname,
3065 rc = mgs_write_log_lmv(env, mgs, fsdb, mti, logname,
3070 rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, mti, logname, "",
3071 fsdb->fsdb_clilov, LUSTRE_SP_CLI, flags);
3073 name_destroy(&logname);
3077 static __inline__ int mgs_param_empty(char *ptr)
3081 if ((tmp = strchr(ptr, '=')) && (*(++tmp) == '\0'))
3086 static int mgs_write_log_failnid_internal(const struct lu_env *env,
3087 struct mgs_device *mgs,
3089 struct mgs_target_info *mti,
3090 char *logname, char *cliname)
3093 struct llog_handle *llh = NULL;
3095 if (mgs_param_empty(mti->mti_params)) {
3096 /* Remove _all_ failnids */
3097 rc = mgs_modify(env, mgs, fsdb, mti, logname,
3098 mti->mti_svname, "add failnid", CM_SKIP);
3099 return rc < 0 ? rc : 0;
3102 /* Otherwise failover nids are additive */
3103 rc = record_start_log(env, mgs, &llh, logname);
3106 /* FIXME this should be a single journal transaction */
3107 rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
3111 rc = mgs_write_log_failnids(env, mti, llh, cliname);
3114 rc = record_marker(env, llh, fsdb, CM_END,
3115 mti->mti_svname, "add failnid");
3117 record_end_log(env, &llh);
3122 /* Add additional failnids to an existing log.
3123 The mdc/osc must have been added to logs first */
3124 /* tcp nids must be in dotted-quad ascii -
3125 we can't resolve hostnames from the kernel. */
3126 static int mgs_write_log_add_failnid(const struct lu_env *env,
3127 struct mgs_device *mgs,
3129 struct mgs_target_info *mti)
3131 char *logname, *cliname;
3135 /* FIXME we currently can't erase the failnids
3136 * given when a target first registers, since they aren't part of
3137 * an "add uuid" stanza
3140 /* Verify that we know about this target */
3141 if (mgs_log_is_empty(env, mgs, mti->mti_svname)) {
3142 LCONSOLE_ERROR_MSG(0x142, "The target %s has not registered "
3143 "yet. It must be started before failnids "
3144 "can be added.\n", mti->mti_svname);
3148 /* Create mdc/osc client name (e.g. lustre-OST0001-osc) */
3149 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
3150 rc = name_create(&cliname, mti->mti_svname, "-mdc");
3151 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
3152 rc = name_create(&cliname, mti->mti_svname, "-osc");
3159 /* Add failover nids to the client log */
3160 rc = name_create(&logname, mti->mti_fsname, "-client");
3162 name_destroy(&cliname);
3166 rc = mgs_write_log_failnid_internal(env, mgs, fsdb,mti,logname,cliname);
3167 name_destroy(&logname);
3168 name_destroy(&cliname);
3172 if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
3173 /* Add OST failover nids to the MDT logs as well */
3176 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
3177 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
3179 rc = name_create_mdt(&logname, mti->mti_fsname, i);
3182 rc = name_create_mdt_osc(&cliname, mti->mti_svname,
3185 name_destroy(&logname);
3188 rc = mgs_write_log_failnid_internal(env, mgs, fsdb,
3191 name_destroy(&cliname);
3192 name_destroy(&logname);
3201 static int mgs_wlp_lcfg(const struct lu_env *env,
3202 struct mgs_device *mgs, struct fs_db *fsdb,
3203 struct mgs_target_info *mti,
3204 char *logname, struct lustre_cfg_bufs *bufs,
3205 char *tgtname, char *ptr)
3207 char comment[MTI_NAME_MAXLEN];
3209 struct llog_cfg_rec *lcr;
3212 /* Erase any old settings of this same parameter */
3213 memcpy(comment, ptr, MTI_NAME_MAXLEN);
3214 comment[MTI_NAME_MAXLEN - 1] = 0;
3215 /* But don't try to match the value. */
3216 tmp = strchr(comment, '=');
3219 /* FIXME we should skip settings that are the same as old values */
3220 rc = mgs_modify(env, mgs, fsdb, mti, logname, tgtname, comment,CM_SKIP);
3223 del = mgs_param_empty(ptr);
3225 LCONSOLE_INFO("%s parameter %s.%s in log %s\n", del ? "Disabling" : rc ?
3226 "Setting" : "Modifying", tgtname, comment, logname);
3228 /* mgs_modify() will return 1 if nothing had to be done */
3234 lustre_cfg_bufs_reset(bufs, tgtname);
3235 lustre_cfg_bufs_set_string(bufs, 1, ptr);
3236 if (mti->mti_flags & LDD_F_PARAM2)
3237 lustre_cfg_bufs_set_string(bufs, 2, LCTL_UPCALL);
3239 lcr = lustre_cfg_rec_new((mti->mti_flags & LDD_F_PARAM2) ?
3240 LCFG_SET_PARAM : LCFG_PARAM, bufs);
3244 rc = mgs_write_log_direct(env, mgs, fsdb, logname, lcr, tgtname,
3246 lustre_cfg_rec_free(lcr);
3250 /* write global variable settings into log */
3251 static int mgs_write_log_sys(const struct lu_env *env,
3252 struct mgs_device *mgs, struct fs_db *fsdb,
3253 struct mgs_target_info *mti, char *sys, char *ptr)
3255 struct mgs_thread_info *mgi = mgs_env_info(env);
3256 struct lustre_cfg *lcfg;
3257 struct llog_cfg_rec *lcr;
3259 int rc, cmd, convert = 1;
3261 if (class_match_param(ptr, PARAM_TIMEOUT, &tmp) == 0) {
3262 cmd = LCFG_SET_TIMEOUT;
3263 } else if (class_match_param(ptr, PARAM_LDLM_TIMEOUT, &tmp) == 0) {
3264 cmd = LCFG_SET_LDLM_TIMEOUT;
3265 /* Check for known params here so we can return error to lctl */
3266 } else if ((class_match_param(ptr, PARAM_AT_MIN, &tmp) == 0) ||
3267 (class_match_param(ptr, PARAM_AT_MAX, &tmp) == 0) ||
3268 (class_match_param(ptr, PARAM_AT_EXTRA, &tmp) == 0) ||
3269 (class_match_param(ptr, PARAM_AT_EARLY_MARGIN, &tmp) == 0) ||
3270 (class_match_param(ptr, PARAM_AT_HISTORY, &tmp) == 0)) {
3272 } else if (class_match_param(ptr, PARAM_JOBID_VAR, &tmp) == 0) {
3273 convert = 0; /* Don't convert string value to integer */
3279 if (mgs_param_empty(ptr))
3280 CDEBUG(D_MGS, "global '%s' removed\n", sys);
3282 CDEBUG(D_MGS, "global '%s' val=%s\n", sys, tmp);
3284 lustre_cfg_bufs_reset(&mgi->mgi_bufs, NULL);
3285 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, sys);
3286 if (!convert && *tmp != '\0')
3287 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 2, tmp);
3288 lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
3292 lcfg = &lcr->lcr_cfg;
3293 lcfg->lcfg_num = convert ? simple_strtoul(tmp, NULL, 0) : 0;
3294 /* truncate the comment to the parameter name */
3298 /* modify all servers and clients */
3299 rc = mgs_write_log_direct_all(env, mgs, fsdb, mti,
3300 *tmp == '\0' ? NULL : lcr,
3301 mti->mti_fsname, sys, 0);
3302 if (rc == 0 && *tmp != '\0') {
3304 case LCFG_SET_TIMEOUT:
3305 if (!obd_timeout_set || lcfg->lcfg_num > obd_timeout)
3306 class_process_config(lcfg);
3308 case LCFG_SET_LDLM_TIMEOUT:
3309 if (!ldlm_timeout_set || lcfg->lcfg_num > ldlm_timeout)
3310 class_process_config(lcfg);
3317 lustre_cfg_rec_free(lcr);
3321 /* write quota settings into log */
3322 static int mgs_write_log_quota(const struct lu_env *env, struct mgs_device *mgs,
3323 struct fs_db *fsdb, struct mgs_target_info *mti,
3324 char *quota, char *ptr)
3326 struct mgs_thread_info *mgi = mgs_env_info(env);
3327 struct llog_cfg_rec *lcr;
3330 int rc, cmd = LCFG_PARAM;
3332 /* support only 'meta' and 'data' pools so far */
3333 if (class_match_param(ptr, QUOTA_METAPOOL_NAME, &tmp) != 0 &&
3334 class_match_param(ptr, QUOTA_DATAPOOL_NAME, &tmp) != 0) {
3335 CERROR("parameter quota.%s isn't supported (only quota.mdt "
3336 "& quota.ost are)\n", ptr);
3341 CDEBUG(D_MGS, "global '%s' removed\n", quota);
3343 CDEBUG(D_MGS, "global '%s'\n", quota);
3345 if (strchr(tmp, 'u') == NULL && strchr(tmp, 'g') == NULL &&
3346 strchr(tmp, 'p') == NULL &&
3347 strcmp(tmp, "none") != 0) {
3348 CERROR("enable option(%s) isn't supported\n", tmp);
3353 lustre_cfg_bufs_reset(&mgi->mgi_bufs, mti->mti_fsname);
3354 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, quota);
3355 lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
3359 /* truncate the comment to the parameter name */
3364 /* XXX we duplicated quota enable information in all server
3365 * config logs, it should be moved to a separate config
3366 * log once we cleanup the config log for global param. */
3367 /* modify all servers */
3368 rc = mgs_write_log_direct_all(env, mgs, fsdb, mti,
3369 *tmp == '\0' ? NULL : lcr,
3370 mti->mti_fsname, quota, 1);
3372 lustre_cfg_rec_free(lcr);
3373 return rc < 0 ? rc : 0;
3376 static int mgs_srpc_set_param_disk(const struct lu_env *env,
3377 struct mgs_device *mgs,
3379 struct mgs_target_info *mti,
3382 struct mgs_thread_info *mgi = mgs_env_info(env);
3383 struct llog_cfg_rec *lcr;
3384 struct llog_handle *llh = NULL;
3386 char *comment, *ptr;
3392 ptr = strchr(param, '=');
3393 LASSERT(ptr != NULL);
3396 OBD_ALLOC(comment, len + 1);
3397 if (comment == NULL)
3399 strncpy(comment, param, len);
3400 comment[len] = '\0';
3403 lustre_cfg_bufs_reset(&mgi->mgi_bufs, mti->mti_svname);
3404 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, param);
3405 lcr = lustre_cfg_rec_new(LCFG_SPTLRPC_CONF, &mgi->mgi_bufs);
3407 GOTO(out_comment, rc = -ENOMEM);
3409 /* construct log name */
3410 rc = name_create(&logname, mti->mti_fsname, "-sptlrpc");
3414 if (mgs_log_is_empty(env, mgs, logname)) {
3415 rc = record_start_log(env, mgs, &llh, logname);
3418 record_end_log(env, &llh);
3421 /* obsolete old one */
3422 rc = mgs_modify(env, mgs, fsdb, mti, logname, mti->mti_svname,
3426 /* write the new one */
3427 rc = mgs_write_log_direct(env, mgs, fsdb, logname, lcr,
3428 mti->mti_svname, comment);
3430 CERROR("%s: error writing log %s: rc = %d\n",
3431 mgs->mgs_obd->obd_name, logname, rc);
3433 name_destroy(&logname);
3435 lustre_cfg_rec_free(lcr);
3437 OBD_FREE(comment, len + 1);
3441 static int mgs_srpc_set_param_udesc_mem(struct fs_db *fsdb,
3446 /* disable the adjustable udesc parameter for now, i.e. use default
3447 * setting that client always ship udesc to MDT if possible. to enable
3448 * it simply remove the following line */
3451 ptr = strchr(param, '=');
3456 if (strcmp(param, PARAM_SRPC_UDESC))
3459 if (strcmp(ptr, "yes") == 0) {
3460 set_bit(FSDB_UDESC, &fsdb->fsdb_flags);
3461 CWARN("Enable user descriptor shipping from client to MDT\n");
3462 } else if (strcmp(ptr, "no") == 0) {
3463 clear_bit(FSDB_UDESC, &fsdb->fsdb_flags);
3464 CWARN("Disable user descriptor shipping from client to MDT\n");
3472 CERROR("Invalid param: %s\n", param);
3476 static int mgs_srpc_set_param_mem(struct fs_db *fsdb,
3480 struct sptlrpc_rule rule;
3481 struct sptlrpc_rule_set *rset;
3485 if (strncmp(param, PARAM_SRPC, sizeof(PARAM_SRPC) - 1) != 0) {
3486 CERROR("Invalid sptlrpc parameter: %s\n", param);
3490 if (strncmp(param, PARAM_SRPC_UDESC,
3491 sizeof(PARAM_SRPC_UDESC) - 1) == 0) {
3492 RETURN(mgs_srpc_set_param_udesc_mem(fsdb, param));
3495 if (strncmp(param, PARAM_SRPC_FLVR, sizeof(PARAM_SRPC_FLVR) - 1) != 0) {
3496 CERROR("Invalid sptlrpc flavor parameter: %s\n", param);
3500 param += sizeof(PARAM_SRPC_FLVR) - 1;
3502 rc = sptlrpc_parse_rule(param, &rule);
3506 /* mgs rules implies must be mgc->mgs */
3507 if (test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
3508 if ((rule.sr_from != LUSTRE_SP_MGC &&
3509 rule.sr_from != LUSTRE_SP_ANY) ||
3510 (rule.sr_to != LUSTRE_SP_MGS &&
3511 rule.sr_to != LUSTRE_SP_ANY))
3515 /* preapre room for this coming rule. svcname format should be:
3516 * - fsname: general rule
3517 * - fsname-tgtname: target-specific rule
3519 if (strchr(svname, '-')) {
3520 struct mgs_tgt_srpc_conf *tgtconf;
3523 for (tgtconf = fsdb->fsdb_srpc_tgt; tgtconf != NULL;
3524 tgtconf = tgtconf->mtsc_next) {
3525 if (!strcmp(tgtconf->mtsc_tgt, svname)) {
3534 OBD_ALLOC_PTR(tgtconf);
3535 if (tgtconf == NULL)
3538 name_len = strlen(svname);
3540 OBD_ALLOC(tgtconf->mtsc_tgt, name_len + 1);
3541 if (tgtconf->mtsc_tgt == NULL) {
3542 OBD_FREE_PTR(tgtconf);
3545 memcpy(tgtconf->mtsc_tgt, svname, name_len);
3547 tgtconf->mtsc_next = fsdb->fsdb_srpc_tgt;
3548 fsdb->fsdb_srpc_tgt = tgtconf;
3551 rset = &tgtconf->mtsc_rset;
3552 } else if (strcmp(svname, MGSSELF_NAME) == 0) {
3553 /* put _mgs related srpc rule directly in mgs ruleset */
3554 rset = &fsdb->fsdb_mgs->mgs_lut.lut_sptlrpc_rset;
3556 rset = &fsdb->fsdb_srpc_gen;
3559 rc = sptlrpc_rule_set_merge(rset, &rule);
3564 static int mgs_srpc_set_param(const struct lu_env *env,
3565 struct mgs_device *mgs,
3567 struct mgs_target_info *mti,
3577 /* keep a copy of original param, which could be destroied
3579 copy_size = strlen(param) + 1;
3580 OBD_ALLOC(copy, copy_size);
3583 memcpy(copy, param, copy_size);
3585 rc = mgs_srpc_set_param_mem(fsdb, mti->mti_svname, param);
3589 /* previous steps guaranteed the syntax is correct */
3590 rc = mgs_srpc_set_param_disk(env, mgs, fsdb, mti, copy);
3594 if (test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
3596 * for mgs rules, make them effective immediately.
3598 LASSERT(fsdb->fsdb_srpc_tgt == NULL);
3599 sptlrpc_target_update_exp_flavor(mgs->mgs_obd,
3600 &fsdb->fsdb_srpc_gen);
3604 OBD_FREE(copy, copy_size);
3608 struct mgs_srpc_read_data {
3609 struct fs_db *msrd_fsdb;
3613 static int mgs_srpc_read_handler(const struct lu_env *env,
3614 struct llog_handle *llh,
3615 struct llog_rec_hdr *rec, void *data)
3617 struct mgs_srpc_read_data *msrd = data;
3618 struct cfg_marker *marker;
3619 struct lustre_cfg *lcfg = REC_DATA(rec);
3620 char *svname, *param;
3624 if (rec->lrh_type != OBD_CFG_REC) {
3625 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
3629 cfg_len = REC_DATA_LEN(rec);
3631 rc = lustre_cfg_sanity_check(lcfg, cfg_len);
3633 CERROR("Insane cfg\n");
3637 if (lcfg->lcfg_command == LCFG_MARKER) {
3638 marker = lustre_cfg_buf(lcfg, 1);
3640 if (marker->cm_flags & CM_START &&
3641 marker->cm_flags & CM_SKIP)
3642 msrd->msrd_skip = 1;
3643 if (marker->cm_flags & CM_END)
3644 msrd->msrd_skip = 0;
3649 if (msrd->msrd_skip)
3652 if (lcfg->lcfg_command != LCFG_SPTLRPC_CONF) {
3653 CERROR("invalid command (%x)\n", lcfg->lcfg_command);
3657 svname = lustre_cfg_string(lcfg, 0);
3658 if (svname == NULL) {
3659 CERROR("svname is empty\n");
3663 param = lustre_cfg_string(lcfg, 1);
3664 if (param == NULL) {
3665 CERROR("param is empty\n");
3669 rc = mgs_srpc_set_param_mem(msrd->msrd_fsdb, svname, param);
3671 CERROR("read sptlrpc record error (%d): %s\n", rc, param);
3676 int mgs_get_fsdb_srpc_from_llog(const struct lu_env *env,
3677 struct mgs_device *mgs,
3680 struct llog_handle *llh = NULL;
3681 struct llog_ctxt *ctxt;
3683 struct mgs_srpc_read_data msrd;
3687 /* construct log name */
3688 rc = name_create(&logname, fsdb->fsdb_name, "-sptlrpc");
3692 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
3693 LASSERT(ctxt != NULL);
3695 if (mgs_log_is_empty(env, mgs, logname))
3698 rc = llog_open(env, ctxt, &llh, NULL, logname,
3706 rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL);
3708 GOTO(out_close, rc);
3710 if (llog_get_size(llh) <= 1)
3711 GOTO(out_close, rc = 0);
3713 msrd.msrd_fsdb = fsdb;
3716 rc = llog_process(env, llh, mgs_srpc_read_handler, (void *)&msrd,
3720 llog_close(env, llh);
3722 llog_ctxt_put(ctxt);
3723 name_destroy(&logname);
3726 CERROR("failed to read sptlrpc config database: %d\n", rc);
3730 static int mgs_write_log_param2(const struct lu_env *env,
3731 struct mgs_device *mgs,
3733 struct mgs_target_info *mti, char *ptr)
3735 struct lustre_cfg_bufs bufs;
3739 CDEBUG(D_MGS, "next param '%s'\n", ptr);
3741 /* PARAM_MGSNODE and PARAM_NETWORK are set only when formating
3742 * or during the inital mount. It can never change after that.
3744 if (!class_match_param(ptr, PARAM_MGSNODE, NULL) ||
3745 !class_match_param(ptr, PARAM_NETWORK, NULL)) {
3750 /* Processed in mgs_write_log_ost. Another value that can't
3751 * be changed by lctl set_param -P.
3753 if (!class_match_param(ptr, PARAM_FAILMODE, NULL)) {
3754 LCONSOLE_ERROR_MSG(0x169,
3755 "%s can only be changed with tunefs.lustre and --writeconf\n",
3761 /* FIXME !!! Support for sptlrpc is incomplete. Currently the change
3762 * doesn't transmit to the client. See LU-7183.
3764 if (!class_match_param(ptr, PARAM_SRPC, NULL)) {
3765 rc = mgs_srpc_set_param(env, mgs, fsdb, mti, ptr);
3769 /* Can't use class_match_param since ptr doesn't start with
3770 * PARAM_FAILNODE. So we look for PARAM_FAILNODE contained in ptr.
3772 if (strstr(ptr, PARAM_FAILNODE)) {
3773 /* Add a failover nidlist. We already processed failovers
3774 * params for new targets in mgs_write_log_target.
3778 /* can't use wildcards with failover.node */
3779 if (strchr(ptr, '*')) {
3784 param = strstr(ptr, PARAM_FAILNODE);
3785 if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
3786 sizeof(mti->mti_params)) {
3791 CDEBUG(D_MGS, "Adding failnode with param %s\n",
3793 rc = mgs_write_log_add_failnid(env, mgs, fsdb, mti);
3797 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, PARAMS_FILENAME, &bufs,
3798 mti->mti_svname, ptr);
3803 /* Permanent settings of all parameters by writing into the appropriate
3804 * configuration logs.
3805 * A parameter with null value ("<param>='\0'") means to erase it out of
3808 static int mgs_write_log_param(const struct lu_env *env,
3809 struct mgs_device *mgs, struct fs_db *fsdb,
3810 struct mgs_target_info *mti, char *ptr)
3812 struct mgs_thread_info *mgi = mgs_env_info(env);
3818 /* For various parameter settings, we have to figure out which logs
3819 care about them (e.g. both mdt and client for lov settings) */
3820 CDEBUG(D_MGS, "next param '%s'\n", ptr);
3822 /* The params are stored in MOUNT_DATA_FILE and modified via
3823 tunefs.lustre, or set using lctl conf_param */
3825 /* Processed in lustre_start_mgc */
3826 if (class_match_param(ptr, PARAM_MGSNODE, NULL) == 0)
3829 /* Processed in ost/mdt */
3830 if (class_match_param(ptr, PARAM_NETWORK, NULL) == 0)
3833 /* Processed in mgs_write_log_ost */
3834 if (class_match_param(ptr, PARAM_FAILMODE, NULL) == 0) {
3835 if (mti->mti_flags & LDD_F_PARAM) {
3836 LCONSOLE_ERROR_MSG(0x169, "%s can only be "
3837 "changed with tunefs.lustre"
3838 "and --writeconf\n", ptr);
3844 if (class_match_param(ptr, PARAM_SRPC, NULL) == 0) {
3845 rc = mgs_srpc_set_param(env, mgs, fsdb, mti, ptr);
3849 if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
3850 /* Add a failover nidlist */
3852 /* We already processed failovers params for new
3853 targets in mgs_write_log_target */
3854 if (mti->mti_flags & LDD_F_PARAM) {
3855 CDEBUG(D_MGS, "Adding failnode\n");
3856 rc = mgs_write_log_add_failnid(env, mgs, fsdb, mti);
3861 if (class_match_param(ptr, PARAM_SYS, &tmp) == 0) {
3862 rc = mgs_write_log_sys(env, mgs, fsdb, mti, ptr, tmp);
3866 if (class_match_param(ptr, PARAM_QUOTA, &tmp) == 0) {
3867 rc = mgs_write_log_quota(env, mgs, fsdb, mti, ptr, tmp);
3871 if (class_match_param(ptr, PARAM_OSC PARAM_ACTIVE, &tmp) == 0 ||
3872 class_match_param(ptr, PARAM_MDC PARAM_ACTIVE, &tmp) == 0) {
3873 /* active=0 means off, anything else means on */
3874 int flag = (*tmp == '0') ? CM_EXCLUDE : 0;
3875 bool deactive_osc = memcmp(ptr, PARAM_OSC PARAM_ACTIVE,
3876 strlen(PARAM_OSC PARAM_ACTIVE)) == 0;
3879 if (!deactive_osc) {
3882 rc = server_name2index(mti->mti_svname, &index, NULL);
3887 LCONSOLE_ERROR_MSG(0x144, "%s: MDC0 can not be"
3888 " (de)activated.\n",
3890 GOTO(end, rc = -EPERM);
3894 LCONSOLE_WARN("Permanently %sactivating %s\n",
3895 flag ? "de" : "re", mti->mti_svname);
3897 rc = name_create(&logname, mti->mti_fsname, "-client");
3900 rc = mgs_modify(env, mgs, fsdb, mti, logname,
3902 deactive_osc ? "add osc" : "add mdc", flag);
3903 name_destroy(&logname);
3908 /* Add to all MDT logs for DNE */
3909 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
3910 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
3912 rc = name_create_mdt(&logname, mti->mti_fsname, i);
3915 rc = mgs_modify(env, mgs, fsdb, mti, logname,
3917 deactive_osc ? "add osc" : "add osp",
3919 name_destroy(&logname);
3925 LCONSOLE_ERROR_MSG(0x145, "Couldn't find %s in"
3926 "log (%d). No permanent "
3927 "changes were made to the "
3929 mti->mti_svname, rc);
3930 if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags))
3931 LCONSOLE_ERROR_MSG(0x146, "This may be"
3936 "update the logs.\n");
3939 /* Fall through to osc/mdc proc for deactivating live
3940 OSC/OSP on running MDT / clients. */
3942 /* Below here, let obd's XXX_process_config methods handle it */
3944 /* All lov. in proc */
3945 if (class_match_param(ptr, PARAM_LOV, NULL) == 0) {
3948 CDEBUG(D_MGS, "lov param %s\n", ptr);
3949 if (!(mti->mti_flags & LDD_F_SV_TYPE_MDT)) {
3950 LCONSOLE_ERROR_MSG(0x147, "LOV params must be "
3951 "set on the MDT, not %s. "
3958 if (mgs_log_is_empty(env, mgs, mti->mti_svname))
3959 GOTO(end, rc = -ENODEV);
3961 rc = name_create_mdt_and_lov(&logname, &mdtlovname, fsdb,
3962 mti->mti_stripe_index);
3965 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, mti->mti_svname,
3966 &mgi->mgi_bufs, mdtlovname, ptr);
3967 name_destroy(&logname);
3968 name_destroy(&mdtlovname);
3973 rc = name_create(&logname, mti->mti_fsname, "-client");
3976 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname, &mgi->mgi_bufs,
3977 fsdb->fsdb_clilov, ptr);
3978 name_destroy(&logname);
3982 /* All osc., mdc., llite. params in proc */
3983 if ((class_match_param(ptr, PARAM_OSC, NULL) == 0) ||
3984 (class_match_param(ptr, PARAM_MDC, NULL) == 0) ||
3985 (class_match_param(ptr, PARAM_LLITE, NULL) == 0)) {
3988 if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
3989 LCONSOLE_ERROR_MSG(0x148, "Upgraded client logs for %s"
3990 " cannot be modified. Consider"
3991 " updating the configuration with"
3994 GOTO(end, rc = -EINVAL);
3996 if (memcmp(ptr, PARAM_LLITE, strlen(PARAM_LLITE)) == 0) {
3997 rc = name_create(&cname, mti->mti_fsname, "-client");
3998 /* Add the client type to match the obdname in
3999 class_config_llog_handler */
4000 } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
4001 rc = name_create(&cname, mti->mti_svname, "-mdc");
4002 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
4003 rc = name_create(&cname, mti->mti_svname, "-osc");
4005 GOTO(end, rc = -EINVAL);
4010 /* Forbid direct update of llite root squash parameters.
4011 * These parameters are indirectly set via the MDT settings.
4013 if ((class_match_param(ptr, PARAM_LLITE, &tmp) == 0) &&
4014 ((memcmp(tmp, "root_squash=", 12) == 0) ||
4015 (memcmp(tmp, "nosquash_nids=", 14) == 0))) {
4016 LCONSOLE_ERROR("%s: root squash parameters can only "
4017 "be updated through MDT component\n",
4019 name_destroy(&cname);
4020 GOTO(end, rc = -EINVAL);
4023 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
4026 rc = name_create(&logname, mti->mti_fsname, "-client");
4028 name_destroy(&cname);
4031 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname, &mgi->mgi_bufs,
4034 /* osc params affect the MDT as well */
4035 if (!rc && (mti->mti_flags & LDD_F_SV_TYPE_OST)) {
4038 for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
4039 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
4041 name_destroy(&cname);
4042 rc = name_create_mdt_osc(&cname, mti->mti_svname,
4044 name_destroy(&logname);
4047 rc = name_create_mdt(&logname,
4048 mti->mti_fsname, i);
4051 if (!mgs_log_is_empty(env, mgs, logname)) {
4052 rc = mgs_wlp_lcfg(env, mgs, fsdb,
4062 /* For mdc activate/deactivate, it affects OSP on MDT as well */
4063 if (class_match_param(ptr, PARAM_MDC PARAM_ACTIVE, &tmp) == 0 &&
4066 char *lodname = NULL;
4067 char *param_str = NULL;
4071 /* replace mdc with osp */
4072 memcpy(ptr, PARAM_OSP, strlen(PARAM_OSP));
4073 rc = server_name2index(mti->mti_svname, &index, NULL);
4075 memcpy(ptr, PARAM_MDC, strlen(PARAM_MDC));
4079 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
4080 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
4086 name_destroy(&logname);
4087 rc = name_create_mdt(&logname, mti->mti_fsname,
4092 if (mgs_log_is_empty(env, mgs, logname))
4095 snprintf(suffix, sizeof(suffix), "-osp-MDT%04x",
4097 name_destroy(&cname);
4098 rc = name_create(&cname, mti->mti_svname,
4103 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,
4104 &mgi->mgi_bufs, cname, ptr);
4108 /* Add configuration log for noitfying LOD
4109 * to active/deactive the OSP. */
4110 name_destroy(¶m_str);
4111 rc = name_create(¶m_str, cname,
4112 (*tmp == '0') ? ".active=0" :
4117 name_destroy(&lodname);
4118 rc = name_create(&lodname, logname, "-mdtlov");
4122 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,
4123 &mgi->mgi_bufs, lodname,
4128 memcpy(ptr, PARAM_MDC, strlen(PARAM_MDC));
4129 name_destroy(&lodname);
4130 name_destroy(¶m_str);
4133 name_destroy(&logname);
4134 name_destroy(&cname);
4138 /* All mdt. params in proc */
4139 if (class_match_param(ptr, PARAM_MDT, &tmp) == 0) {
4143 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
4144 if (strncmp(mti->mti_svname, mti->mti_fsname,
4145 MTI_NAME_MAXLEN) == 0)
4146 /* device is unspecified completely? */
4147 rc = LDD_F_SV_TYPE_MDT | LDD_F_SV_ALL;
4149 rc = server_name2index(mti->mti_svname, &idx, NULL);
4152 if ((rc & LDD_F_SV_TYPE_MDT) == 0)
4154 if (rc & LDD_F_SV_ALL) {
4155 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
4157 fsdb->fsdb_mdt_index_map))
4159 rc = name_create_mdt(&logname,
4160 mti->mti_fsname, i);
4163 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti,
4164 logname, &mgi->mgi_bufs,
4166 name_destroy(&logname);
4171 if ((memcmp(tmp, "root_squash=", 12) == 0) ||
4172 (memcmp(tmp, "nosquash_nids=", 14) == 0)) {
4173 LCONSOLE_ERROR("%s: root squash parameters "
4174 "cannot be applied to a single MDT\n",
4176 GOTO(end, rc = -EINVAL);
4178 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti,
4179 mti->mti_svname, &mgi->mgi_bufs,
4180 mti->mti_svname, ptr);
4185 /* root squash settings are also applied to llite
4186 * config log (see LU-1778) */
4188 ((memcmp(tmp, "root_squash=", 12) == 0) ||
4189 (memcmp(tmp, "nosquash_nids=", 14) == 0))) {
4193 rc = name_create(&cname, mti->mti_fsname, "-client");
4196 rc = name_create(&logname, mti->mti_fsname, "-client");
4198 name_destroy(&cname);
4201 rc = name_create(&ptr2, PARAM_LLITE, tmp);
4203 name_destroy(&cname);
4204 name_destroy(&logname);
4207 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,
4208 &mgi->mgi_bufs, cname, ptr2);
4209 name_destroy(&ptr2);
4210 name_destroy(&logname);
4211 name_destroy(&cname);
4216 /* All mdd., ost. and osd. params in proc */
4217 if ((class_match_param(ptr, PARAM_MDD, NULL) == 0) ||
4218 (class_match_param(ptr, PARAM_LOD, NULL) == 0) ||
4219 (class_match_param(ptr, PARAM_OST, NULL) == 0) ||
4220 (class_match_param(ptr, PARAM_OSD, NULL) == 0)) {
4221 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
4222 if (mgs_log_is_empty(env, mgs, mti->mti_svname))
4223 GOTO(end, rc = -ENODEV);
4225 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, mti->mti_svname,
4226 &mgi->mgi_bufs, mti->mti_svname, ptr);
4230 LCONSOLE_WARN("Ignoring unrecognized param '%s'\n", ptr);
4234 CERROR("err %d on param '%s'\n", rc, ptr);
4239 int mgs_write_log_target(const struct lu_env *env, struct mgs_device *mgs,
4240 struct mgs_target_info *mti, struct fs_db *fsdb)
4247 /* set/check the new target index */
4248 rc = mgs_set_index(env, mgs, mti);
4252 if (rc == EALREADY) {
4253 LCONSOLE_WARN("Found index %d for %s, updating log\n",
4254 mti->mti_stripe_index, mti->mti_svname);
4255 /* We would like to mark old log sections as invalid
4256 and add new log sections in the client and mdt logs.
4257 But if we add new sections, then live clients will
4258 get repeat setup instructions for already running
4259 osc's. So don't update the client/mdt logs. */
4260 mti->mti_flags &= ~LDD_F_UPDATE;
4264 OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_WRITE_TARGET_DELAY, cfs_fail_val > 0 ?
4267 mutex_lock(&fsdb->fsdb_mutex);
4269 if (mti->mti_flags &
4270 (LDD_F_VIRGIN | LDD_F_UPGRADE14 | LDD_F_WRITECONF)) {
4271 /* Generate a log from scratch */
4272 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
4273 rc = mgs_write_log_mdt(env, mgs, fsdb, mti);
4274 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
4275 rc = mgs_write_log_ost(env, mgs, fsdb, mti);
4277 CERROR("Unknown target type %#x, can't create log for "
4278 "%s\n", mti->mti_flags, mti->mti_svname);
4281 CERROR("Can't write logs for %s (%d)\n",
4282 mti->mti_svname, rc);
4286 /* Just update the params from tunefs in mgs_write_log_params */
4287 CDEBUG(D_MGS, "Update params for %s\n", mti->mti_svname);
4288 mti->mti_flags |= LDD_F_PARAM;
4291 /* allocate temporary buffer, where class_get_next_param will
4292 make copy of a current parameter */
4293 OBD_ALLOC(buf, strlen(mti->mti_params) + 1);
4295 GOTO(out_up, rc = -ENOMEM);
4296 params = mti->mti_params;
4297 while (params != NULL) {
4298 rc = class_get_next_param(¶ms, buf);
4301 /* there is no next parameter, that is
4306 CDEBUG(D_MGS, "remaining string: '%s', param: '%s'\n",
4308 rc = mgs_write_log_param(env, mgs, fsdb, mti, buf);
4313 OBD_FREE(buf, strlen(mti->mti_params) + 1);
4316 mutex_unlock(&fsdb->fsdb_mutex);
4320 int mgs_erase_log(const struct lu_env *env, struct mgs_device *mgs, char *name)
4322 struct llog_ctxt *ctxt;
4325 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
4327 CERROR("%s: MGS config context doesn't exist\n",
4328 mgs->mgs_obd->obd_name);
4331 rc = llog_erase(env, ctxt, NULL, name);
4332 /* llog may not exist */
4335 llog_ctxt_put(ctxt);
4339 CERROR("%s: failed to clear log %s: %d\n",
4340 mgs->mgs_obd->obd_name, name, rc);
4345 /* erase all logs for the given fs */
4346 int mgs_erase_logs(const struct lu_env *env, struct mgs_device *mgs,
4349 struct list_head log_list;
4350 struct mgs_direntry *dirent, *n;
4351 char barrier_name[20] = {};
4354 int rc, len = strlen(fsname);
4357 mutex_lock(&mgs->mgs_mutex);
4359 /* Find all the logs in the CONFIGS directory */
4360 rc = class_dentry_readdir(env, mgs, &log_list);
4362 mutex_unlock(&mgs->mgs_mutex);
4366 if (list_empty(&log_list)) {
4367 mutex_unlock(&mgs->mgs_mutex);
4371 snprintf(barrier_name, sizeof(barrier_name) - 1, "%s-%s",
4372 fsname, BARRIER_FILENAME);
4373 /* Delete the barrier fsdb */
4374 mgs_remove_fsdb_by_name(mgs, barrier_name);
4375 /* Delete the fs db */
4376 mgs_remove_fsdb_by_name(mgs, fsname);
4377 mutex_unlock(&mgs->mgs_mutex);
4379 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4380 list_del_init(&dirent->mde_list);
4381 suffix = strrchr(dirent->mde_name, '-');
4382 if (suffix != NULL) {
4383 if ((len == suffix - dirent->mde_name) &&
4384 (strncmp(fsname, dirent->mde_name, len) == 0)) {
4385 CDEBUG(D_MGS, "Removing log %s\n",
4387 mgs_erase_log(env, mgs, dirent->mde_name);
4391 mgs_direntry_free(dirent);
4400 /* list all logs for the given fs */
4401 int mgs_list_logs(const struct lu_env *env, struct mgs_device *mgs,
4402 struct obd_ioctl_data *data)
4404 struct list_head log_list;
4405 struct mgs_direntry *dirent, *n;
4411 /* Find all the logs in the CONFIGS directory */
4412 rc = class_dentry_readdir(env, mgs, &log_list);
4416 out = data->ioc_bulk;
4417 remains = data->ioc_inllen1;
4418 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4419 list_del_init(&dirent->mde_list);
4420 suffix = strrchr(dirent->mde_name, '-');
4421 if (suffix != NULL) {
4422 l = snprintf(out, remains, "config_log: %s\n",
4427 mgs_direntry_free(dirent);
4434 struct mgs_lcfg_fork_data {
4435 struct lustre_cfg_bufs mlfd_bufs;
4436 struct mgs_device *mlfd_mgs;
4437 struct llog_handle *mlfd_llh;
4438 const char *mlfd_oldname;
4439 const char *mlfd_newname;
4443 static bool contain_valid_fsname(char *buf, const char *fsname,
4444 int buflen, int namelen)
4446 if (buflen < namelen)
4449 if (memcmp(buf, fsname, namelen) != 0)
4452 if (buf[namelen] != '\0' && buf[namelen] != '-')
4458 static int mgs_lcfg_fork_handler(const struct lu_env *env,
4459 struct llog_handle *o_llh,
4460 struct llog_rec_hdr *o_rec, void *data)
4462 struct mgs_lcfg_fork_data *mlfd = data;
4463 struct lustre_cfg_bufs *n_bufs = &mlfd->mlfd_bufs;
4464 struct lustre_cfg *o_lcfg = (struct lustre_cfg *)(o_rec + 1);
4465 struct llog_cfg_rec *lcr;
4467 char *n_buf = mlfd->mlfd_data;
4469 int o_namelen = strlen(mlfd->mlfd_oldname);
4470 int n_namelen = strlen(mlfd->mlfd_newname);
4471 int diff = n_namelen - o_namelen;
4472 __u32 cmd = o_lcfg->lcfg_command;
4473 __u32 cnt = o_lcfg->lcfg_bufcount;
4479 o_buf = lustre_cfg_buf(o_lcfg, 0);
4480 o_buflen = o_lcfg->lcfg_buflens[0];
4481 if (contain_valid_fsname(o_buf, mlfd->mlfd_oldname, o_buflen,
4483 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4484 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4485 o_buflen - o_namelen);
4486 lustre_cfg_bufs_reset(n_bufs, n_buf);
4487 n_buf += cfs_size_round(o_buflen + diff);
4489 lustre_cfg_bufs_reset(n_bufs, o_buflen != 0 ? o_buf : NULL);
4494 struct cfg_marker *o_marker;
4495 struct cfg_marker *n_marker;
4499 CDEBUG(D_MGS, "Unknown cfg marker entry with %d "
4504 /* buf[1] is marker */
4505 o_buf = lustre_cfg_buf(o_lcfg, 1);
4506 o_buflen = o_lcfg->lcfg_buflens[1];
4507 o_marker = (struct cfg_marker *)o_buf;
4508 if (!contain_valid_fsname(o_marker->cm_tgtname,
4510 sizeof(o_marker->cm_tgtname),
4512 lustre_cfg_bufs_set(n_bufs, 1, o_marker,
4517 n_marker = (struct cfg_marker *)n_buf;
4518 *n_marker = *o_marker;
4519 memcpy(n_marker->cm_tgtname, mlfd->mlfd_newname, n_namelen);
4520 tgt_namelen = strlen(o_marker->cm_tgtname);
4521 if (tgt_namelen > o_namelen)
4522 memcpy(n_marker->cm_tgtname + n_namelen,
4523 o_marker->cm_tgtname + o_namelen,
4524 tgt_namelen - o_namelen);
4525 n_marker->cm_tgtname[tgt_namelen + diff] = '\0';
4526 lustre_cfg_bufs_set(n_bufs, 1, n_marker, sizeof(*n_marker));
4530 case LCFG_SET_PARAM: {
4531 for (i = 1; i < cnt; i++)
4532 /* buf[i] is the param value, reuse it directly */
4533 lustre_cfg_bufs_set(n_bufs, i,
4534 lustre_cfg_buf(o_lcfg, i),
4535 o_lcfg->lcfg_buflens[i]);
4541 case LCFG_POOL_DEL: {
4542 if (cnt < 3 || cnt > 4) {
4543 CDEBUG(D_MGS, "Unknown cfg pool (%x) entry with %d "
4544 "buffers\n", cmd, cnt);
4548 /* buf[1] is fsname */
4549 o_buf = lustre_cfg_buf(o_lcfg, 1);
4550 o_buflen = o_lcfg->lcfg_buflens[1];
4551 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4552 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4553 o_buflen - o_namelen);
4554 lustre_cfg_bufs_set(n_bufs, 1, n_buf, o_buflen + diff);
4555 n_buf += cfs_size_round(o_buflen + diff);
4557 /* buf[2] is the pool name, reuse it directly */
4558 lustre_cfg_bufs_set(n_bufs, 2, lustre_cfg_buf(o_lcfg, 2),
4559 o_lcfg->lcfg_buflens[2]);
4564 /* buf[3] is ostname */
4565 o_buf = lustre_cfg_buf(o_lcfg, 3);
4566 o_buflen = o_lcfg->lcfg_buflens[3];
4567 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4568 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4569 o_buflen - o_namelen);
4570 lustre_cfg_bufs_set(n_bufs, 3, n_buf, o_buflen + diff);
4575 o_buflen = o_lcfg->lcfg_buflens[1];
4576 if (o_buflen == sizeof(struct lov_desc) ||
4577 o_buflen == sizeof(struct lmv_desc)) {
4583 o_buf = lustre_cfg_buf(o_lcfg, 1);
4584 if (o_buflen == sizeof(struct lov_desc)) {
4585 struct lov_desc *o_desc =
4586 (struct lov_desc *)o_buf;
4587 struct lov_desc *n_desc =
4588 (struct lov_desc *)n_buf;
4591 o_uuid = o_desc->ld_uuid.uuid;
4592 n_uuid = n_desc->ld_uuid.uuid;
4593 uuid_len = sizeof(o_desc->ld_uuid.uuid);
4595 struct lmv_desc *o_desc =
4596 (struct lmv_desc *)o_buf;
4597 struct lmv_desc *n_desc =
4598 (struct lmv_desc *)n_buf;
4601 o_uuid = o_desc->ld_uuid.uuid;
4602 n_uuid = n_desc->ld_uuid.uuid;
4603 uuid_len = sizeof(o_desc->ld_uuid.uuid);
4606 if (unlikely(!contain_valid_fsname(o_uuid,
4607 mlfd->mlfd_oldname, uuid_len,
4609 lustre_cfg_bufs_set(n_bufs, 1, o_buf,
4614 memcpy(n_uuid, mlfd->mlfd_newname, n_namelen);
4615 uuid_len = strlen(o_uuid);
4616 if (uuid_len > o_namelen)
4617 memcpy(n_uuid + n_namelen,
4619 uuid_len - o_namelen);
4620 n_uuid[uuid_len + diff] = '\0';
4621 lustre_cfg_bufs_set(n_bufs, 1, n_buf, o_buflen);
4623 } /* else case fall through */
4624 } /* else case fall through */
4627 for (i = 1; i < cnt; i++) {
4628 o_buflen = o_lcfg->lcfg_buflens[i];
4632 o_buf = lustre_cfg_buf(o_lcfg, i);
4633 if (!contain_valid_fsname(o_buf, mlfd->mlfd_oldname,
4634 o_buflen, o_namelen)) {
4635 lustre_cfg_bufs_set(n_bufs, i, o_buf, o_buflen);
4639 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4640 if (o_buflen == o_namelen) {
4641 lustre_cfg_bufs_set(n_bufs, i, n_buf,
4643 n_buf += cfs_size_round(n_namelen);
4647 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4648 o_buflen - o_namelen);
4649 lustre_cfg_bufs_set(n_bufs, i, n_buf, o_buflen + diff);
4650 n_buf += cfs_size_round(o_buflen + diff);
4656 lcr = lustre_cfg_rec_new(cmd, n_bufs);
4660 lcr->lcr_cfg = *o_lcfg;
4661 rc = llog_write(env, mlfd->mlfd_llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
4662 lustre_cfg_rec_free(lcr);
4667 static int mgs_lcfg_fork_one(const struct lu_env *env, struct mgs_device *mgs,
4668 struct mgs_direntry *mde, const char *oldname,
4669 const char *newname)
4671 struct llog_handle *old_llh = NULL;
4672 struct llog_handle *new_llh = NULL;
4673 struct llog_ctxt *ctxt = NULL;
4674 struct mgs_lcfg_fork_data *mlfd = NULL;
4675 char *name_buf = NULL;
4677 int old_namelen = strlen(oldname);
4678 int new_namelen = strlen(newname);
4682 name_buflen = mde->mde_len + new_namelen - old_namelen;
4683 OBD_ALLOC(name_buf, name_buflen);
4687 memcpy(name_buf, newname, new_namelen);
4688 memcpy(name_buf + new_namelen, mde->mde_name + old_namelen,
4689 mde->mde_len - old_namelen);
4691 CDEBUG(D_MGS, "Fork the config-log from %s to %s\n",
4692 mde->mde_name, name_buf);
4694 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
4697 rc = llog_open_create(env, ctxt, &new_llh, NULL, name_buf);
4701 rc = llog_init_handle(env, new_llh, LLOG_F_IS_PLAIN, NULL);
4705 if (unlikely(mgs_log_is_empty(env, mgs, mde->mde_name)))
4708 rc = llog_open(env, ctxt, &old_llh, NULL, mde->mde_name,
4713 rc = llog_init_handle(env, old_llh, LLOG_F_IS_PLAIN, NULL);
4717 new_llh->lgh_hdr->llh_tgtuuid = old_llh->lgh_hdr->llh_tgtuuid;
4719 OBD_ALLOC(mlfd, LLOG_MIN_CHUNK_SIZE);
4721 GOTO(out, rc = -ENOMEM);
4723 mlfd->mlfd_mgs = mgs;
4724 mlfd->mlfd_llh = new_llh;
4725 mlfd->mlfd_oldname = oldname;
4726 mlfd->mlfd_newname = newname;
4728 rc = llog_process(env, old_llh, mgs_lcfg_fork_handler, mlfd, NULL);
4729 OBD_FREE(mlfd, LLOG_MIN_CHUNK_SIZE);
4735 llog_close(env, old_llh);
4737 llog_close(env, new_llh);
4739 OBD_FREE(name_buf, name_buflen);
4741 llog_ctxt_put(ctxt);
4746 int mgs_lcfg_fork(const struct lu_env *env, struct mgs_device *mgs,
4747 const char *oldname, const char *newname)
4749 struct list_head log_list;
4750 struct mgs_direntry *dirent, *n;
4751 int olen = strlen(oldname);
4752 int nlen = strlen(newname);
4757 if (unlikely(!oldname || oldname[0] == '\0' ||
4758 !newname || newname[0] == '\0'))
4761 if (strcmp(oldname, newname) == 0)
4764 /* lock it to prevent fork/erase/register in parallel. */
4765 mutex_lock(&mgs->mgs_mutex);
4767 rc = class_dentry_readdir(env, mgs, &log_list);
4769 mutex_unlock(&mgs->mgs_mutex);
4773 if (list_empty(&log_list)) {
4774 mutex_unlock(&mgs->mgs_mutex);
4778 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4781 ptr = strrchr(dirent->mde_name, '-');
4783 int tlen = ptr - dirent->mde_name;
4786 strncmp(newname, dirent->mde_name, tlen) == 0)
4787 GOTO(out, rc = -EEXIST);
4790 strncmp(oldname, dirent->mde_name, tlen) == 0)
4794 list_del_init(&dirent->mde_list);
4795 mgs_direntry_free(dirent);
4798 if (list_empty(&log_list)) {
4799 mutex_unlock(&mgs->mgs_mutex);
4803 list_for_each_entry(dirent, &log_list, mde_list) {
4804 rc = mgs_lcfg_fork_one(env, mgs, dirent, oldname, newname);
4812 mutex_unlock(&mgs->mgs_mutex);
4814 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4815 list_del_init(&dirent->mde_list);
4816 mgs_direntry_free(dirent);
4819 if (rc && count > 0)
4820 mgs_erase_logs(env, mgs, newname);
4825 int mgs_lcfg_erase(const struct lu_env *env, struct mgs_device *mgs,
4831 if (unlikely(!fsname || fsname[0] == '\0'))
4834 rc = mgs_erase_logs(env, mgs, fsname);
4839 static int mgs_xattr_del(const struct lu_env *env, struct dt_object *obj)
4841 struct dt_device *dev;
4842 struct thandle *th = NULL;
4847 dev = container_of0(obj->do_lu.lo_dev, struct dt_device, dd_lu_dev);
4848 th = dt_trans_create(env, dev);
4850 RETURN(PTR_ERR(th));
4852 rc = dt_declare_xattr_del(env, obj, XATTR_TARGET_RENAME, th);
4856 rc = dt_trans_start_local(env, dev, th);
4860 dt_write_lock(env, obj, 0);
4861 rc = dt_xattr_del(env, obj, XATTR_TARGET_RENAME, th);
4866 dt_write_unlock(env, obj);
4869 dt_trans_stop(env, dev, th);
4874 int mgs_lcfg_rename(const struct lu_env *env, struct mgs_device *mgs)
4876 struct list_head log_list;
4877 struct mgs_direntry *dirent, *n;
4879 struct lu_buf buf = {
4881 .lb_len = sizeof(fsname)
4887 rc = class_dentry_readdir(env, mgs, &log_list);
4891 if (list_empty(&log_list))
4894 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4895 struct dt_object *o = NULL;
4900 list_del_init(&dirent->mde_list);
4901 ptr = strrchr(dirent->mde_name, '-');
4905 len = ptr - dirent->mde_name;
4906 if (unlikely(len >= sizeof(oldname))) {
4907 CDEBUG(D_MGS, "Skip invalid configuration file %s\n",
4912 o = local_file_find(env, mgs->mgs_los, mgs->mgs_configs_dir,
4916 CDEBUG(D_MGS, "Fail to locate file %s: rc = %d\n",
4917 dirent->mde_name, rc);
4921 rc = dt_xattr_get(env, o, &buf, XATTR_TARGET_RENAME);
4927 "Fail to get EA for %s: rc = %d\n",
4928 dirent->mde_name, rc);
4932 if (unlikely(rc == len &&
4933 memcmp(fsname, dirent->mde_name, len) == 0)) {
4934 /* The new fsname is the same as the old one. */
4935 rc = mgs_xattr_del(env, o);
4939 memcpy(oldname, dirent->mde_name, len);
4940 oldname[len] = '\0';
4942 rc = mgs_lcfg_fork_one(env, mgs, dirent, oldname, fsname);
4943 if (rc && rc != -EEXIST) {
4944 CDEBUG(D_MGS, "Fail to fork %s: rc = %d\n",
4945 dirent->mde_name, rc);
4949 rc = mgs_erase_log(env, mgs, dirent->mde_name);
4951 CDEBUG(D_MGS, "Fail to erase old %s: rc = %d\n",
4952 dirent->mde_name, rc);
4953 /* keep it there if failed to remove it. */
4958 if (o && !IS_ERR(o))
4959 lu_object_put(env, &o->do_lu);
4961 mgs_direntry_free(dirent);
4966 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4967 list_del_init(&dirent->mde_list);
4968 mgs_direntry_free(dirent);
4974 /* Setup _mgs fsdb and log
4976 int mgs__mgs_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs)
4978 struct fs_db *fsdb = NULL;
4982 rc = mgs_find_or_make_fsdb(env, mgs, MGSSELF_NAME, &fsdb);
4984 mgs_put_fsdb(mgs, fsdb);
4989 /* Setup params fsdb and log
4991 int mgs_params_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs)
4993 struct fs_db *fsdb = NULL;
4994 struct llog_handle *params_llh = NULL;
4998 rc = mgs_find_or_make_fsdb(env, mgs, PARAMS_FILENAME, &fsdb);
5000 mutex_lock(&fsdb->fsdb_mutex);
5001 rc = record_start_log(env, mgs, ¶ms_llh, PARAMS_FILENAME);
5003 rc = record_end_log(env, ¶ms_llh);
5004 mutex_unlock(&fsdb->fsdb_mutex);
5005 mgs_put_fsdb(mgs, fsdb);
5011 /* Cleanup params fsdb and log
5013 int mgs_params_fsdb_cleanup(const struct lu_env *env, struct mgs_device *mgs)
5017 rc = mgs_erase_logs(env, mgs, PARAMS_FILENAME);
5018 return rc == -ENOENT ? 0 : rc;
5022 * Fill in the mgs_target_info based on data devname and param provide.
5024 * @env thread context
5026 * @mti mgs target info. We want to set this based other paramters
5027 * passed to this function. Once setup we write it to the config
5029 * @devname optional OBD device name
5030 * @param string that contains both what tunable to set and the value to
5033 * RETURN 0 for success
5034 * negative error number on failure
5036 static int mgs_set_conf_param(const struct lu_env *env, struct mgs_device *mgs,
5037 struct mgs_target_info *mti, const char *devname,
5040 struct fs_db *fsdb = NULL;
5045 /* lustre, lustre-mdtlov, lustre-client, lustre-MDT0000 */
5049 /* We have two possible cases here:
5051 * 1) the device name embedded in the param:
5052 * lustre-OST0000.osc.max_dirty_mb=32
5054 * 2) the file system name is embedded in
5055 * the param: lustre.sys.at.min=0
5057 len = strcspn(param, ".=");
5058 if (!len || param[len] == '=')
5061 if (len >= sizeof(mti->mti_svname))
5064 snprintf(mti->mti_svname, sizeof(mti->mti_svname),
5065 "%.*s", (int)len, param);
5068 if (strlcpy(mti->mti_svname, devname, sizeof(mti->mti_svname)) >=
5069 sizeof(mti->mti_svname))
5073 if (!strlen(mti->mti_svname)) {
5074 LCONSOLE_ERROR_MSG(0x14d, "No target specified: %s\n", param);
5078 dev_type = mgs_parse_devname(mti->mti_svname, mti->mti_fsname,
5079 &mti->mti_stripe_index);
5081 /* For this case we have an invalid obd device name */
5083 CDEBUG(D_MGS, "%s don't contain an index\n", mti->mti_svname);
5084 strlcpy(mti->mti_fsname, mti->mti_svname, MTI_NAME_MAXLEN);
5087 /* Not an obd device, assume devname is the fsname.
5088 * User might of only provided fsname and not obd device
5091 CDEBUG(D_MGS, "%s is seen as a file system name\n", mti->mti_svname);
5092 strlcpy(mti->mti_fsname, mti->mti_svname, MTI_NAME_MAXLEN);
5097 GOTO(out, rc = dev_type);
5099 /* param related to llite isn't allowed to set by OST or MDT */
5100 if (dev_type & LDD_F_SV_TYPE_OST ||
5101 dev_type & LDD_F_SV_TYPE_MDT) {
5102 /* param related to llite isn't allowed to set by OST
5105 if (!strncmp(param, PARAM_LLITE,
5106 sizeof(PARAM_LLITE) - 1))
5107 GOTO(out, rc = -EINVAL);
5109 /* Strip -osc or -mdc suffix from svname */
5110 if (server_make_name(dev_type, mti->mti_stripe_index,
5111 mti->mti_fsname, mti->mti_svname,
5112 sizeof(mti->mti_svname)))
5113 GOTO(out, rc = -EINVAL);
5118 if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
5119 sizeof(mti->mti_params))
5120 GOTO(out, rc = -E2BIG);
5122 CDEBUG(D_MGS, "set_conf_param fs='%s' device='%s' param='%s'\n",
5123 mti->mti_fsname, mti->mti_svname, mti->mti_params);
5125 rc = mgs_find_or_make_fsdb(env, mgs, mti->mti_fsname, &fsdb);
5129 if (!test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags) &&
5130 test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
5131 CERROR("No filesystem targets for %s. cfg_device from lctl "
5132 "is '%s'\n", mti->mti_fsname, mti->mti_svname);
5133 mgs_unlink_fsdb(mgs, fsdb);
5134 GOTO(out, rc = -EINVAL);
5138 * Revoke lock so everyone updates. Should be alright if
5139 * someone was already reading while we were updating the logs,
5140 * so we don't really need to hold the lock while we're
5143 mti->mti_flags = dev_type | LDD_F_PARAM;
5144 mutex_lock(&fsdb->fsdb_mutex);
5145 rc = mgs_write_log_param(env, mgs, fsdb, mti, mti->mti_params);
5146 mutex_unlock(&fsdb->fsdb_mutex);
5147 mgs_revoke_lock(mgs, fsdb, CONFIG_T_CONFIG);
5151 mgs_put_fsdb(mgs, fsdb);
5156 static int mgs_set_param2(const struct lu_env *env, struct mgs_device *mgs,
5157 struct mgs_target_info *mti, const char *param)
5159 struct fs_db *fsdb = NULL;
5164 if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
5165 sizeof(mti->mti_params))
5166 GOTO(out, rc = -E2BIG);
5168 /* obdname2fsname reports devname as an obd device */
5169 len = strcspn(param, ".=");
5170 if (len && param[len] != '=') {
5174 ptr = strchr(param, '.');
5176 len = strlen(param);
5179 if (len >= sizeof(mti->mti_svname))
5180 GOTO(out, rc = -E2BIG);
5182 snprintf(mti->mti_svname, sizeof(mti->mti_svname), "%.*s",
5185 obdname2fsname(mti->mti_svname, mti->mti_fsname,
5186 sizeof(mti->mti_fsname));
5188 snprintf(mti->mti_svname, sizeof(mti->mti_svname), "general");
5191 CDEBUG(D_MGS, "set_param2 fs='%s' device='%s' param='%s'\n",
5192 mti->mti_fsname, mti->mti_svname, mti->mti_params);
5194 /* The return value should be the device type i.e LDD_F_SV_TYPE_XXX.
5195 * A returned error tells us we don't have a target obd device.
5197 dev_type = server_name2index(mti->mti_svname, &mti->mti_stripe_index,
5202 /* the return value should be the device type i.e LDD_F_SV_TYPE_XXX.
5203 * Strip -osc or -mdc suffix from svname
5205 if ((dev_type & LDD_F_SV_TYPE_OST || dev_type & LDD_F_SV_TYPE_MDT) &&
5206 server_make_name(dev_type, mti->mti_stripe_index,
5207 mti->mti_fsname, mti->mti_svname,
5208 sizeof(mti->mti_svname)))
5209 GOTO(out, rc = -EINVAL);
5211 rc = mgs_find_or_make_fsdb(env, mgs, PARAMS_FILENAME, &fsdb);
5215 * Revoke lock so everyone updates. Should be alright if
5216 * someone was already reading while we were updating the logs,
5217 * so we don't really need to hold the lock while we're
5220 mti->mti_flags = dev_type | LDD_F_PARAM2;
5221 mutex_lock(&fsdb->fsdb_mutex);
5222 rc = mgs_write_log_param2(env, mgs, fsdb, mti, mti->mti_params);
5223 mutex_unlock(&fsdb->fsdb_mutex);
5224 mgs_revoke_lock(mgs, fsdb, CONFIG_T_PARAMS);
5225 mgs_put_fsdb(mgs, fsdb);
5230 /* Set a permanent (config log) param for a target or fs
5232 * @lcfg buf0 may contain the device (testfs-MDT0000) name
5233 * buf1 contains the single parameter
5235 int mgs_set_param(const struct lu_env *env, struct mgs_device *mgs,
5236 struct lustre_cfg *lcfg)
5238 const char *param = lustre_cfg_string(lcfg, 1);
5239 struct mgs_target_info *mti;
5242 /* Create a fake mti to hold everything */
5247 print_lustre_cfg(lcfg);
5249 if (lcfg->lcfg_command == LCFG_PARAM) {
5250 /* For the case of lctl conf_param devname can be
5251 * lustre, lustre-mdtlov, lustre-client, lustre-MDT0000
5253 const char *devname = lustre_cfg_string(lcfg, 0);
5255 rc = mgs_set_conf_param(env, mgs, mti, devname, param);
5257 /* In the case of lctl set_param -P lcfg[0] will always
5258 * be 'general'. At least for now.
5260 rc = mgs_set_param2(env, mgs, mti, param);
5268 static int mgs_write_log_pool(const struct lu_env *env,
5269 struct mgs_device *mgs, char *logname,
5270 struct fs_db *fsdb, char *tgtname,
5271 enum lcfg_command_type cmd,
5272 char *fsname, char *poolname,
5273 char *ostname, char *comment)
5275 struct llog_handle *llh = NULL;
5278 rc = record_start_log(env, mgs, &llh, logname);
5281 rc = record_marker(env, llh, fsdb, CM_START, tgtname, comment);
5284 rc = record_base(env, llh, tgtname, 0, cmd,
5285 fsname, poolname, ostname, NULL);
5288 rc = record_marker(env, llh, fsdb, CM_END, tgtname, comment);
5290 record_end_log(env, &llh);
5294 int mgs_nodemap_cmd(const struct lu_env *env, struct mgs_device *mgs,
5295 enum lcfg_command_type cmd, const char *nodemap_name,
5306 case LCFG_NODEMAP_ADD:
5307 rc = nodemap_add(nodemap_name);
5309 case LCFG_NODEMAP_DEL:
5310 rc = nodemap_del(nodemap_name);
5312 case LCFG_NODEMAP_ADD_RANGE:
5313 rc = nodemap_parse_range(param, nid);
5316 rc = nodemap_add_range(nodemap_name, nid);
5318 case LCFG_NODEMAP_DEL_RANGE:
5319 rc = nodemap_parse_range(param, nid);
5322 rc = nodemap_del_range(nodemap_name, nid);
5324 case LCFG_NODEMAP_ADMIN:
5325 bool_switch = simple_strtoul(param, NULL, 10);
5326 rc = nodemap_set_allow_root(nodemap_name, bool_switch);
5328 case LCFG_NODEMAP_DENY_UNKNOWN:
5329 bool_switch = simple_strtoul(param, NULL, 10);
5330 rc = nodemap_set_deny_unknown(nodemap_name, bool_switch);
5332 case LCFG_NODEMAP_AUDIT_MODE:
5333 rc = kstrtoul(param, 10, (unsigned long *)&bool_switch);
5335 rc = nodemap_set_audit_mode(nodemap_name, bool_switch);
5337 case LCFG_NODEMAP_MAP_MODE:
5338 if (strcmp("both", param) == 0)
5339 rc = nodemap_set_mapping_mode(nodemap_name,
5341 else if (strcmp("uid_only", param) == 0)
5342 rc = nodemap_set_mapping_mode(nodemap_name,
5343 NODEMAP_MAP_UID_ONLY);
5344 else if (strcmp("gid_only", param) == 0)
5345 rc = nodemap_set_mapping_mode(nodemap_name,
5346 NODEMAP_MAP_GID_ONLY);
5350 case LCFG_NODEMAP_TRUSTED:
5351 bool_switch = simple_strtoul(param, NULL, 10);
5352 rc = nodemap_set_trust_client_ids(nodemap_name, bool_switch);
5354 case LCFG_NODEMAP_SQUASH_UID:
5355 int_id = simple_strtoul(param, NULL, 10);
5356 rc = nodemap_set_squash_uid(nodemap_name, int_id);
5358 case LCFG_NODEMAP_SQUASH_GID:
5359 int_id = simple_strtoul(param, NULL, 10);
5360 rc = nodemap_set_squash_gid(nodemap_name, int_id);
5362 case LCFG_NODEMAP_ADD_UIDMAP:
5363 case LCFG_NODEMAP_ADD_GIDMAP:
5364 rc = nodemap_parse_idmap(param, idmap);
5367 if (cmd == LCFG_NODEMAP_ADD_UIDMAP)
5368 rc = nodemap_add_idmap(nodemap_name, NODEMAP_UID,
5371 rc = nodemap_add_idmap(nodemap_name, NODEMAP_GID,
5374 case LCFG_NODEMAP_DEL_UIDMAP:
5375 case LCFG_NODEMAP_DEL_GIDMAP:
5376 rc = nodemap_parse_idmap(param, idmap);
5379 if (cmd == LCFG_NODEMAP_DEL_UIDMAP)
5380 rc = nodemap_del_idmap(nodemap_name, NODEMAP_UID,
5383 rc = nodemap_del_idmap(nodemap_name, NODEMAP_GID,
5386 case LCFG_NODEMAP_SET_FILESET:
5387 rc = nodemap_set_fileset(nodemap_name, param);
5396 int mgs_pool_cmd(const struct lu_env *env, struct mgs_device *mgs,
5397 enum lcfg_command_type cmd, char *fsname,
5398 char *poolname, char *ostname)
5403 char *label = NULL, *canceled_label = NULL;
5405 struct mgs_target_info *mti = NULL;
5406 bool checked = false;
5407 bool locked = false;
5412 rc = mgs_find_or_make_fsdb(env, mgs, fsname, &fsdb);
5414 CERROR("Can't get db for %s\n", fsname);
5417 if (test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
5418 CERROR("%s is not defined\n", fsname);
5420 GOTO(out_fsdb, rc = -EINVAL);
5423 label_sz = 10 + strlen(fsname) + strlen(poolname);
5425 /* check if ostname match fsname */
5426 if (ostname != NULL) {
5429 ptr = strrchr(ostname, '-');
5430 if ((ptr == NULL) ||
5431 (strncmp(fsname, ostname, ptr-ostname) != 0))
5433 label_sz += strlen(ostname);
5436 OBD_ALLOC(label, label_sz);
5438 GOTO(out_fsdb, rc = -ENOMEM);
5443 "new %s.%s", fsname, poolname);
5447 "add %s.%s.%s", fsname, poolname, ostname);
5450 OBD_ALLOC(canceled_label, label_sz);
5451 if (canceled_label == NULL)
5452 GOTO(out_label, rc = -ENOMEM);
5454 "rem %s.%s.%s", fsname, poolname, ostname);
5455 sprintf(canceled_label,
5456 "add %s.%s.%s", fsname, poolname, ostname);
5459 OBD_ALLOC(canceled_label, label_sz);
5460 if (canceled_label == NULL)
5461 GOTO(out_label, rc = -ENOMEM);
5463 "del %s.%s", fsname, poolname);
5464 sprintf(canceled_label,
5465 "new %s.%s", fsname, poolname);
5473 GOTO(out_cancel, rc = -ENOMEM);
5474 strncpy(mti->mti_svname, "lov pool", sizeof(mti->mti_svname));
5476 mutex_lock(&fsdb->fsdb_mutex);
5478 /* write pool def to all MDT logs */
5479 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
5480 if (test_bit(i, fsdb->fsdb_mdt_index_map)) {
5481 rc = name_create_mdt_and_lov(&logname, &lovname,
5486 if (!checked && (canceled_label == NULL)) {
5487 rc = mgs_check_marker(env, mgs, fsdb, mti,
5488 logname, lovname, label);
5490 name_destroy(&logname);
5491 name_destroy(&lovname);
5493 rc = (rc == LLOG_PROC_BREAK ?
5498 if (canceled_label != NULL)
5499 rc = mgs_modify(env, mgs, fsdb, mti, logname,
5500 lovname, canceled_label,
5504 rc = mgs_write_log_pool(env, mgs, logname,
5508 name_destroy(&logname);
5509 name_destroy(&lovname);
5515 rc = name_create(&logname, fsname, "-client");
5519 if (!checked && (canceled_label == NULL)) {
5520 rc = mgs_check_marker(env, mgs, fsdb, mti, logname,
5521 fsdb->fsdb_clilov, label);
5523 name_destroy(&logname);
5524 GOTO(out_mti, rc = (rc == LLOG_PROC_BREAK ?
5528 if (canceled_label != NULL) {
5529 rc = mgs_modify(env, mgs, fsdb, mti, logname,
5530 fsdb->fsdb_clilov, canceled_label, CM_SKIP);
5532 name_destroy(&logname);
5537 rc = mgs_write_log_pool(env, mgs, logname, fsdb, fsdb->fsdb_clilov,
5538 cmd, fsname, poolname, ostname, label);
5539 mutex_unlock(&fsdb->fsdb_mutex);
5541 name_destroy(&logname);
5542 /* request for update */
5543 mgs_revoke_lock(mgs, fsdb, CONFIG_T_CONFIG);
5549 mutex_unlock(&fsdb->fsdb_mutex);
5553 if (canceled_label != NULL)
5554 OBD_FREE(canceled_label, label_sz);
5556 OBD_FREE(label, label_sz);
5559 mgs_unlink_fsdb(mgs, fsdb);
5560 mgs_put_fsdb(mgs, fsdb);