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 & (LDD_F_VIRGIN | LDD_F_WRITECONF)) {
4270 /* Generate a log from scratch */
4271 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
4272 rc = mgs_write_log_mdt(env, mgs, fsdb, mti);
4273 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
4274 rc = mgs_write_log_ost(env, mgs, fsdb, mti);
4276 CERROR("Unknown target type %#x, can't create log for %s\n",
4277 mti->mti_flags, mti->mti_svname);
4280 CERROR("Can't write logs for %s (%d)\n",
4281 mti->mti_svname, rc);
4285 /* Just update the params from tunefs in mgs_write_log_params */
4286 CDEBUG(D_MGS, "Update params for %s\n", mti->mti_svname);
4287 mti->mti_flags |= LDD_F_PARAM;
4290 /* allocate temporary buffer, where class_get_next_param will
4291 make copy of a current parameter */
4292 OBD_ALLOC(buf, strlen(mti->mti_params) + 1);
4294 GOTO(out_up, rc = -ENOMEM);
4295 params = mti->mti_params;
4296 while (params != NULL) {
4297 rc = class_get_next_param(¶ms, buf);
4300 /* there is no next parameter, that is
4305 CDEBUG(D_MGS, "remaining string: '%s', param: '%s'\n",
4307 rc = mgs_write_log_param(env, mgs, fsdb, mti, buf);
4312 OBD_FREE(buf, strlen(mti->mti_params) + 1);
4315 mutex_unlock(&fsdb->fsdb_mutex);
4319 int mgs_erase_log(const struct lu_env *env, struct mgs_device *mgs, char *name)
4321 struct llog_ctxt *ctxt;
4324 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
4326 CERROR("%s: MGS config context doesn't exist\n",
4327 mgs->mgs_obd->obd_name);
4330 rc = llog_erase(env, ctxt, NULL, name);
4331 /* llog may not exist */
4334 llog_ctxt_put(ctxt);
4338 CERROR("%s: failed to clear log %s: %d\n",
4339 mgs->mgs_obd->obd_name, name, rc);
4344 /* erase all logs for the given fs */
4345 int mgs_erase_logs(const struct lu_env *env, struct mgs_device *mgs,
4348 struct list_head log_list;
4349 struct mgs_direntry *dirent, *n;
4350 char barrier_name[20] = {};
4353 int rc, len = strlen(fsname);
4356 mutex_lock(&mgs->mgs_mutex);
4358 /* Find all the logs in the CONFIGS directory */
4359 rc = class_dentry_readdir(env, mgs, &log_list);
4361 mutex_unlock(&mgs->mgs_mutex);
4365 if (list_empty(&log_list)) {
4366 mutex_unlock(&mgs->mgs_mutex);
4370 snprintf(barrier_name, sizeof(barrier_name) - 1, "%s-%s",
4371 fsname, BARRIER_FILENAME);
4372 /* Delete the barrier fsdb */
4373 mgs_remove_fsdb_by_name(mgs, barrier_name);
4374 /* Delete the fs db */
4375 mgs_remove_fsdb_by_name(mgs, fsname);
4376 mutex_unlock(&mgs->mgs_mutex);
4378 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4379 list_del_init(&dirent->mde_list);
4380 suffix = strrchr(dirent->mde_name, '-');
4381 if (suffix != NULL) {
4382 if ((len == suffix - dirent->mde_name) &&
4383 (strncmp(fsname, dirent->mde_name, len) == 0)) {
4384 CDEBUG(D_MGS, "Removing log %s\n",
4386 mgs_erase_log(env, mgs, dirent->mde_name);
4390 mgs_direntry_free(dirent);
4399 /* list all logs for the given fs */
4400 int mgs_list_logs(const struct lu_env *env, struct mgs_device *mgs,
4401 struct obd_ioctl_data *data)
4403 struct list_head log_list;
4404 struct mgs_direntry *dirent, *n;
4410 /* Find all the logs in the CONFIGS directory */
4411 rc = class_dentry_readdir(env, mgs, &log_list);
4415 out = data->ioc_bulk;
4416 remains = data->ioc_inllen1;
4417 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4418 list_del_init(&dirent->mde_list);
4419 suffix = strrchr(dirent->mde_name, '-');
4420 if (suffix != NULL) {
4421 l = snprintf(out, remains, "config_log: %s\n",
4426 mgs_direntry_free(dirent);
4433 struct mgs_lcfg_fork_data {
4434 struct lustre_cfg_bufs mlfd_bufs;
4435 struct mgs_device *mlfd_mgs;
4436 struct llog_handle *mlfd_llh;
4437 const char *mlfd_oldname;
4438 const char *mlfd_newname;
4442 static bool contain_valid_fsname(char *buf, const char *fsname,
4443 int buflen, int namelen)
4445 if (buflen < namelen)
4448 if (memcmp(buf, fsname, namelen) != 0)
4451 if (buf[namelen] != '\0' && buf[namelen] != '-')
4457 static int mgs_lcfg_fork_handler(const struct lu_env *env,
4458 struct llog_handle *o_llh,
4459 struct llog_rec_hdr *o_rec, void *data)
4461 struct mgs_lcfg_fork_data *mlfd = data;
4462 struct lustre_cfg_bufs *n_bufs = &mlfd->mlfd_bufs;
4463 struct lustre_cfg *o_lcfg = (struct lustre_cfg *)(o_rec + 1);
4464 struct llog_cfg_rec *lcr;
4466 char *n_buf = mlfd->mlfd_data;
4468 int o_namelen = strlen(mlfd->mlfd_oldname);
4469 int n_namelen = strlen(mlfd->mlfd_newname);
4470 int diff = n_namelen - o_namelen;
4471 __u32 cmd = o_lcfg->lcfg_command;
4472 __u32 cnt = o_lcfg->lcfg_bufcount;
4478 o_buf = lustre_cfg_buf(o_lcfg, 0);
4479 o_buflen = o_lcfg->lcfg_buflens[0];
4480 if (contain_valid_fsname(o_buf, mlfd->mlfd_oldname, o_buflen,
4482 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4483 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4484 o_buflen - o_namelen);
4485 lustre_cfg_bufs_reset(n_bufs, n_buf);
4486 n_buf += cfs_size_round(o_buflen + diff);
4488 lustre_cfg_bufs_reset(n_bufs, o_buflen != 0 ? o_buf : NULL);
4493 struct cfg_marker *o_marker;
4494 struct cfg_marker *n_marker;
4498 CDEBUG(D_MGS, "Unknown cfg marker entry with %d "
4503 /* buf[1] is marker */
4504 o_buf = lustre_cfg_buf(o_lcfg, 1);
4505 o_buflen = o_lcfg->lcfg_buflens[1];
4506 o_marker = (struct cfg_marker *)o_buf;
4507 if (!contain_valid_fsname(o_marker->cm_tgtname,
4509 sizeof(o_marker->cm_tgtname),
4511 lustre_cfg_bufs_set(n_bufs, 1, o_marker,
4516 n_marker = (struct cfg_marker *)n_buf;
4517 *n_marker = *o_marker;
4518 memcpy(n_marker->cm_tgtname, mlfd->mlfd_newname, n_namelen);
4519 tgt_namelen = strlen(o_marker->cm_tgtname);
4520 if (tgt_namelen > o_namelen)
4521 memcpy(n_marker->cm_tgtname + n_namelen,
4522 o_marker->cm_tgtname + o_namelen,
4523 tgt_namelen - o_namelen);
4524 n_marker->cm_tgtname[tgt_namelen + diff] = '\0';
4525 lustre_cfg_bufs_set(n_bufs, 1, n_marker, sizeof(*n_marker));
4529 case LCFG_SET_PARAM: {
4530 for (i = 1; i < cnt; i++)
4531 /* buf[i] is the param value, reuse it directly */
4532 lustre_cfg_bufs_set(n_bufs, i,
4533 lustre_cfg_buf(o_lcfg, i),
4534 o_lcfg->lcfg_buflens[i]);
4540 case LCFG_POOL_DEL: {
4541 if (cnt < 3 || cnt > 4) {
4542 CDEBUG(D_MGS, "Unknown cfg pool (%x) entry with %d "
4543 "buffers\n", cmd, cnt);
4547 /* buf[1] is fsname */
4548 o_buf = lustre_cfg_buf(o_lcfg, 1);
4549 o_buflen = o_lcfg->lcfg_buflens[1];
4550 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4551 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4552 o_buflen - o_namelen);
4553 lustre_cfg_bufs_set(n_bufs, 1, n_buf, o_buflen + diff);
4554 n_buf += cfs_size_round(o_buflen + diff);
4556 /* buf[2] is the pool name, reuse it directly */
4557 lustre_cfg_bufs_set(n_bufs, 2, lustre_cfg_buf(o_lcfg, 2),
4558 o_lcfg->lcfg_buflens[2]);
4563 /* buf[3] is ostname */
4564 o_buf = lustre_cfg_buf(o_lcfg, 3);
4565 o_buflen = o_lcfg->lcfg_buflens[3];
4566 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4567 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4568 o_buflen - o_namelen);
4569 lustre_cfg_bufs_set(n_bufs, 3, n_buf, o_buflen + diff);
4574 o_buflen = o_lcfg->lcfg_buflens[1];
4575 if (o_buflen == sizeof(struct lov_desc) ||
4576 o_buflen == sizeof(struct lmv_desc)) {
4582 o_buf = lustre_cfg_buf(o_lcfg, 1);
4583 if (o_buflen == sizeof(struct lov_desc)) {
4584 struct lov_desc *o_desc =
4585 (struct lov_desc *)o_buf;
4586 struct lov_desc *n_desc =
4587 (struct lov_desc *)n_buf;
4590 o_uuid = o_desc->ld_uuid.uuid;
4591 n_uuid = n_desc->ld_uuid.uuid;
4592 uuid_len = sizeof(o_desc->ld_uuid.uuid);
4594 struct lmv_desc *o_desc =
4595 (struct lmv_desc *)o_buf;
4596 struct lmv_desc *n_desc =
4597 (struct lmv_desc *)n_buf;
4600 o_uuid = o_desc->ld_uuid.uuid;
4601 n_uuid = n_desc->ld_uuid.uuid;
4602 uuid_len = sizeof(o_desc->ld_uuid.uuid);
4605 if (unlikely(!contain_valid_fsname(o_uuid,
4606 mlfd->mlfd_oldname, uuid_len,
4608 lustre_cfg_bufs_set(n_bufs, 1, o_buf,
4613 memcpy(n_uuid, mlfd->mlfd_newname, n_namelen);
4614 uuid_len = strlen(o_uuid);
4615 if (uuid_len > o_namelen)
4616 memcpy(n_uuid + n_namelen,
4618 uuid_len - o_namelen);
4619 n_uuid[uuid_len + diff] = '\0';
4620 lustre_cfg_bufs_set(n_bufs, 1, n_buf, o_buflen);
4622 } /* else case fall through */
4623 } /* else case fall through */
4626 for (i = 1; i < cnt; i++) {
4627 o_buflen = o_lcfg->lcfg_buflens[i];
4631 o_buf = lustre_cfg_buf(o_lcfg, i);
4632 if (!contain_valid_fsname(o_buf, mlfd->mlfd_oldname,
4633 o_buflen, o_namelen)) {
4634 lustre_cfg_bufs_set(n_bufs, i, o_buf, o_buflen);
4638 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4639 if (o_buflen == o_namelen) {
4640 lustre_cfg_bufs_set(n_bufs, i, n_buf,
4642 n_buf += cfs_size_round(n_namelen);
4646 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4647 o_buflen - o_namelen);
4648 lustre_cfg_bufs_set(n_bufs, i, n_buf, o_buflen + diff);
4649 n_buf += cfs_size_round(o_buflen + diff);
4655 lcr = lustre_cfg_rec_new(cmd, n_bufs);
4659 lcr->lcr_cfg = *o_lcfg;
4660 rc = llog_write(env, mlfd->mlfd_llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
4661 lustre_cfg_rec_free(lcr);
4666 static int mgs_lcfg_fork_one(const struct lu_env *env, struct mgs_device *mgs,
4667 struct mgs_direntry *mde, const char *oldname,
4668 const char *newname)
4670 struct llog_handle *old_llh = NULL;
4671 struct llog_handle *new_llh = NULL;
4672 struct llog_ctxt *ctxt = NULL;
4673 struct mgs_lcfg_fork_data *mlfd = NULL;
4674 char *name_buf = NULL;
4676 int old_namelen = strlen(oldname);
4677 int new_namelen = strlen(newname);
4681 name_buflen = mde->mde_len + new_namelen - old_namelen;
4682 OBD_ALLOC(name_buf, name_buflen);
4686 memcpy(name_buf, newname, new_namelen);
4687 memcpy(name_buf + new_namelen, mde->mde_name + old_namelen,
4688 mde->mde_len - old_namelen);
4690 CDEBUG(D_MGS, "Fork the config-log from %s to %s\n",
4691 mde->mde_name, name_buf);
4693 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
4696 rc = llog_open_create(env, ctxt, &new_llh, NULL, name_buf);
4700 rc = llog_init_handle(env, new_llh, LLOG_F_IS_PLAIN, NULL);
4704 if (unlikely(mgs_log_is_empty(env, mgs, mde->mde_name)))
4707 rc = llog_open(env, ctxt, &old_llh, NULL, mde->mde_name,
4712 rc = llog_init_handle(env, old_llh, LLOG_F_IS_PLAIN, NULL);
4716 new_llh->lgh_hdr->llh_tgtuuid = old_llh->lgh_hdr->llh_tgtuuid;
4718 OBD_ALLOC(mlfd, LLOG_MIN_CHUNK_SIZE);
4720 GOTO(out, rc = -ENOMEM);
4722 mlfd->mlfd_mgs = mgs;
4723 mlfd->mlfd_llh = new_llh;
4724 mlfd->mlfd_oldname = oldname;
4725 mlfd->mlfd_newname = newname;
4727 rc = llog_process(env, old_llh, mgs_lcfg_fork_handler, mlfd, NULL);
4728 OBD_FREE(mlfd, LLOG_MIN_CHUNK_SIZE);
4734 llog_close(env, old_llh);
4736 llog_close(env, new_llh);
4738 OBD_FREE(name_buf, name_buflen);
4740 llog_ctxt_put(ctxt);
4745 int mgs_lcfg_fork(const struct lu_env *env, struct mgs_device *mgs,
4746 const char *oldname, const char *newname)
4748 struct list_head log_list;
4749 struct mgs_direntry *dirent, *n;
4750 int olen = strlen(oldname);
4751 int nlen = strlen(newname);
4756 if (unlikely(!oldname || oldname[0] == '\0' ||
4757 !newname || newname[0] == '\0'))
4760 if (strcmp(oldname, newname) == 0)
4763 /* lock it to prevent fork/erase/register in parallel. */
4764 mutex_lock(&mgs->mgs_mutex);
4766 rc = class_dentry_readdir(env, mgs, &log_list);
4768 mutex_unlock(&mgs->mgs_mutex);
4772 if (list_empty(&log_list)) {
4773 mutex_unlock(&mgs->mgs_mutex);
4777 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4780 ptr = strrchr(dirent->mde_name, '-');
4782 int tlen = ptr - dirent->mde_name;
4785 strncmp(newname, dirent->mde_name, tlen) == 0)
4786 GOTO(out, rc = -EEXIST);
4789 strncmp(oldname, dirent->mde_name, tlen) == 0)
4793 list_del_init(&dirent->mde_list);
4794 mgs_direntry_free(dirent);
4797 if (list_empty(&log_list)) {
4798 mutex_unlock(&mgs->mgs_mutex);
4802 list_for_each_entry(dirent, &log_list, mde_list) {
4803 rc = mgs_lcfg_fork_one(env, mgs, dirent, oldname, newname);
4811 mutex_unlock(&mgs->mgs_mutex);
4813 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4814 list_del_init(&dirent->mde_list);
4815 mgs_direntry_free(dirent);
4818 if (rc && count > 0)
4819 mgs_erase_logs(env, mgs, newname);
4824 int mgs_lcfg_erase(const struct lu_env *env, struct mgs_device *mgs,
4830 if (unlikely(!fsname || fsname[0] == '\0'))
4833 rc = mgs_erase_logs(env, mgs, fsname);
4838 static int mgs_xattr_del(const struct lu_env *env, struct dt_object *obj)
4840 struct dt_device *dev;
4841 struct thandle *th = NULL;
4846 dev = container_of0(obj->do_lu.lo_dev, struct dt_device, dd_lu_dev);
4847 th = dt_trans_create(env, dev);
4849 RETURN(PTR_ERR(th));
4851 rc = dt_declare_xattr_del(env, obj, XATTR_TARGET_RENAME, th);
4855 rc = dt_trans_start_local(env, dev, th);
4859 dt_write_lock(env, obj, 0);
4860 rc = dt_xattr_del(env, obj, XATTR_TARGET_RENAME, th);
4865 dt_write_unlock(env, obj);
4868 dt_trans_stop(env, dev, th);
4873 int mgs_lcfg_rename(const struct lu_env *env, struct mgs_device *mgs)
4875 struct list_head log_list;
4876 struct mgs_direntry *dirent, *n;
4878 struct lu_buf buf = {
4880 .lb_len = sizeof(fsname)
4886 rc = class_dentry_readdir(env, mgs, &log_list);
4890 if (list_empty(&log_list))
4893 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4894 struct dt_object *o = NULL;
4899 list_del_init(&dirent->mde_list);
4900 ptr = strrchr(dirent->mde_name, '-');
4904 len = ptr - dirent->mde_name;
4905 if (unlikely(len >= sizeof(oldname))) {
4906 CDEBUG(D_MGS, "Skip invalid configuration file %s\n",
4911 o = local_file_find(env, mgs->mgs_los, mgs->mgs_configs_dir,
4915 CDEBUG(D_MGS, "Fail to locate file %s: rc = %d\n",
4916 dirent->mde_name, rc);
4920 rc = dt_xattr_get(env, o, &buf, XATTR_TARGET_RENAME);
4926 "Fail to get EA for %s: rc = %d\n",
4927 dirent->mde_name, rc);
4931 if (unlikely(rc == len &&
4932 memcmp(fsname, dirent->mde_name, len) == 0)) {
4933 /* The new fsname is the same as the old one. */
4934 rc = mgs_xattr_del(env, o);
4938 memcpy(oldname, dirent->mde_name, len);
4939 oldname[len] = '\0';
4941 rc = mgs_lcfg_fork_one(env, mgs, dirent, oldname, fsname);
4942 if (rc && rc != -EEXIST) {
4943 CDEBUG(D_MGS, "Fail to fork %s: rc = %d\n",
4944 dirent->mde_name, rc);
4948 rc = mgs_erase_log(env, mgs, dirent->mde_name);
4950 CDEBUG(D_MGS, "Fail to erase old %s: rc = %d\n",
4951 dirent->mde_name, rc);
4952 /* keep it there if failed to remove it. */
4957 if (o && !IS_ERR(o))
4958 lu_object_put(env, &o->do_lu);
4960 mgs_direntry_free(dirent);
4965 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4966 list_del_init(&dirent->mde_list);
4967 mgs_direntry_free(dirent);
4973 /* Setup _mgs fsdb and log
4975 int mgs__mgs_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs)
4977 struct fs_db *fsdb = NULL;
4981 rc = mgs_find_or_make_fsdb(env, mgs, MGSSELF_NAME, &fsdb);
4983 mgs_put_fsdb(mgs, fsdb);
4988 /* Setup params fsdb and log
4990 int mgs_params_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs)
4992 struct fs_db *fsdb = NULL;
4993 struct llog_handle *params_llh = NULL;
4997 rc = mgs_find_or_make_fsdb(env, mgs, PARAMS_FILENAME, &fsdb);
4999 mutex_lock(&fsdb->fsdb_mutex);
5000 rc = record_start_log(env, mgs, ¶ms_llh, PARAMS_FILENAME);
5002 rc = record_end_log(env, ¶ms_llh);
5003 mutex_unlock(&fsdb->fsdb_mutex);
5004 mgs_put_fsdb(mgs, fsdb);
5010 /* Cleanup params fsdb and log
5012 int mgs_params_fsdb_cleanup(const struct lu_env *env, struct mgs_device *mgs)
5016 rc = mgs_erase_logs(env, mgs, PARAMS_FILENAME);
5017 return rc == -ENOENT ? 0 : rc;
5021 * Fill in the mgs_target_info based on data devname and param provide.
5023 * @env thread context
5025 * @mti mgs target info. We want to set this based other paramters
5026 * passed to this function. Once setup we write it to the config
5028 * @devname optional OBD device name
5029 * @param string that contains both what tunable to set and the value to
5032 * RETURN 0 for success
5033 * negative error number on failure
5035 static int mgs_set_conf_param(const struct lu_env *env, struct mgs_device *mgs,
5036 struct mgs_target_info *mti, const char *devname,
5039 struct fs_db *fsdb = NULL;
5044 /* lustre, lustre-mdtlov, lustre-client, lustre-MDT0000 */
5048 /* We have two possible cases here:
5050 * 1) the device name embedded in the param:
5051 * lustre-OST0000.osc.max_dirty_mb=32
5053 * 2) the file system name is embedded in
5054 * the param: lustre.sys.at.min=0
5056 len = strcspn(param, ".=");
5057 if (!len || param[len] == '=')
5060 if (len >= sizeof(mti->mti_svname))
5063 snprintf(mti->mti_svname, sizeof(mti->mti_svname),
5064 "%.*s", (int)len, param);
5067 if (strlcpy(mti->mti_svname, devname, sizeof(mti->mti_svname)) >=
5068 sizeof(mti->mti_svname))
5072 if (!strlen(mti->mti_svname)) {
5073 LCONSOLE_ERROR_MSG(0x14d, "No target specified: %s\n", param);
5077 dev_type = mgs_parse_devname(mti->mti_svname, mti->mti_fsname,
5078 &mti->mti_stripe_index);
5080 /* For this case we have an invalid obd device name */
5082 CDEBUG(D_MGS, "%s don't contain an index\n", mti->mti_svname);
5083 strlcpy(mti->mti_fsname, mti->mti_svname, MTI_NAME_MAXLEN);
5086 /* Not an obd device, assume devname is the fsname.
5087 * User might of only provided fsname and not obd device
5090 CDEBUG(D_MGS, "%s is seen as a file system name\n", mti->mti_svname);
5091 strlcpy(mti->mti_fsname, mti->mti_svname, MTI_NAME_MAXLEN);
5096 GOTO(out, rc = dev_type);
5098 /* param related to llite isn't allowed to set by OST or MDT */
5099 if (dev_type & LDD_F_SV_TYPE_OST ||
5100 dev_type & LDD_F_SV_TYPE_MDT) {
5101 /* param related to llite isn't allowed to set by OST
5104 if (!strncmp(param, PARAM_LLITE,
5105 sizeof(PARAM_LLITE) - 1))
5106 GOTO(out, rc = -EINVAL);
5108 /* Strip -osc or -mdc suffix from svname */
5109 if (server_make_name(dev_type, mti->mti_stripe_index,
5110 mti->mti_fsname, mti->mti_svname,
5111 sizeof(mti->mti_svname)))
5112 GOTO(out, rc = -EINVAL);
5117 if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
5118 sizeof(mti->mti_params))
5119 GOTO(out, rc = -E2BIG);
5121 CDEBUG(D_MGS, "set_conf_param fs='%s' device='%s' param='%s'\n",
5122 mti->mti_fsname, mti->mti_svname, mti->mti_params);
5124 rc = mgs_find_or_make_fsdb(env, mgs, mti->mti_fsname, &fsdb);
5128 if (!test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags) &&
5129 test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
5130 CERROR("No filesystem targets for %s. cfg_device from lctl "
5131 "is '%s'\n", mti->mti_fsname, mti->mti_svname);
5132 mgs_unlink_fsdb(mgs, fsdb);
5133 GOTO(out, rc = -EINVAL);
5137 * Revoke lock so everyone updates. Should be alright if
5138 * someone was already reading while we were updating the logs,
5139 * so we don't really need to hold the lock while we're
5142 mti->mti_flags = dev_type | LDD_F_PARAM;
5143 mutex_lock(&fsdb->fsdb_mutex);
5144 rc = mgs_write_log_param(env, mgs, fsdb, mti, mti->mti_params);
5145 mutex_unlock(&fsdb->fsdb_mutex);
5146 mgs_revoke_lock(mgs, fsdb, CONFIG_T_CONFIG);
5150 mgs_put_fsdb(mgs, fsdb);
5155 static int mgs_set_param2(const struct lu_env *env, struct mgs_device *mgs,
5156 struct mgs_target_info *mti, const char *param)
5158 struct fs_db *fsdb = NULL;
5163 if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
5164 sizeof(mti->mti_params))
5165 GOTO(out, rc = -E2BIG);
5167 /* obdname2fsname reports devname as an obd device */
5168 len = strcspn(param, ".=");
5169 if (len && param[len] != '=') {
5173 ptr = strchr(param, '.');
5175 len = strlen(param);
5178 if (len >= sizeof(mti->mti_svname))
5179 GOTO(out, rc = -E2BIG);
5181 snprintf(mti->mti_svname, sizeof(mti->mti_svname), "%.*s",
5184 obdname2fsname(mti->mti_svname, mti->mti_fsname,
5185 sizeof(mti->mti_fsname));
5187 snprintf(mti->mti_svname, sizeof(mti->mti_svname), "general");
5190 CDEBUG(D_MGS, "set_param2 fs='%s' device='%s' param='%s'\n",
5191 mti->mti_fsname, mti->mti_svname, mti->mti_params);
5193 /* The return value should be the device type i.e LDD_F_SV_TYPE_XXX.
5194 * A returned error tells us we don't have a target obd device.
5196 dev_type = server_name2index(mti->mti_svname, &mti->mti_stripe_index,
5201 /* the return value should be the device type i.e LDD_F_SV_TYPE_XXX.
5202 * Strip -osc or -mdc suffix from svname
5204 if ((dev_type & LDD_F_SV_TYPE_OST || dev_type & LDD_F_SV_TYPE_MDT) &&
5205 server_make_name(dev_type, mti->mti_stripe_index,
5206 mti->mti_fsname, mti->mti_svname,
5207 sizeof(mti->mti_svname)))
5208 GOTO(out, rc = -EINVAL);
5210 rc = mgs_find_or_make_fsdb(env, mgs, PARAMS_FILENAME, &fsdb);
5214 * Revoke lock so everyone updates. Should be alright if
5215 * someone was already reading while we were updating the logs,
5216 * so we don't really need to hold the lock while we're
5219 mti->mti_flags = dev_type | LDD_F_PARAM2;
5220 mutex_lock(&fsdb->fsdb_mutex);
5221 rc = mgs_write_log_param2(env, mgs, fsdb, mti, mti->mti_params);
5222 mutex_unlock(&fsdb->fsdb_mutex);
5223 mgs_revoke_lock(mgs, fsdb, CONFIG_T_PARAMS);
5224 mgs_put_fsdb(mgs, fsdb);
5229 /* Set a permanent (config log) param for a target or fs
5231 * @lcfg buf0 may contain the device (testfs-MDT0000) name
5232 * buf1 contains the single parameter
5234 int mgs_set_param(const struct lu_env *env, struct mgs_device *mgs,
5235 struct lustre_cfg *lcfg)
5237 const char *param = lustre_cfg_string(lcfg, 1);
5238 struct mgs_target_info *mti;
5241 /* Create a fake mti to hold everything */
5246 print_lustre_cfg(lcfg);
5248 if (lcfg->lcfg_command == LCFG_PARAM) {
5249 /* For the case of lctl conf_param devname can be
5250 * lustre, lustre-mdtlov, lustre-client, lustre-MDT0000
5252 const char *devname = lustre_cfg_string(lcfg, 0);
5254 rc = mgs_set_conf_param(env, mgs, mti, devname, param);
5256 /* In the case of lctl set_param -P lcfg[0] will always
5257 * be 'general'. At least for now.
5259 rc = mgs_set_param2(env, mgs, mti, param);
5267 static int mgs_write_log_pool(const struct lu_env *env,
5268 struct mgs_device *mgs, char *logname,
5269 struct fs_db *fsdb, char *tgtname,
5270 enum lcfg_command_type cmd,
5271 char *fsname, char *poolname,
5272 char *ostname, char *comment)
5274 struct llog_handle *llh = NULL;
5277 rc = record_start_log(env, mgs, &llh, logname);
5280 rc = record_marker(env, llh, fsdb, CM_START, tgtname, comment);
5283 rc = record_base(env, llh, tgtname, 0, cmd,
5284 fsname, poolname, ostname, NULL);
5287 rc = record_marker(env, llh, fsdb, CM_END, tgtname, comment);
5289 record_end_log(env, &llh);
5293 int mgs_nodemap_cmd(const struct lu_env *env, struct mgs_device *mgs,
5294 enum lcfg_command_type cmd, const char *nodemap_name,
5305 case LCFG_NODEMAP_ADD:
5306 rc = nodemap_add(nodemap_name);
5308 case LCFG_NODEMAP_DEL:
5309 rc = nodemap_del(nodemap_name);
5311 case LCFG_NODEMAP_ADD_RANGE:
5312 rc = nodemap_parse_range(param, nid);
5315 rc = nodemap_add_range(nodemap_name, nid);
5317 case LCFG_NODEMAP_DEL_RANGE:
5318 rc = nodemap_parse_range(param, nid);
5321 rc = nodemap_del_range(nodemap_name, nid);
5323 case LCFG_NODEMAP_ADMIN:
5324 bool_switch = simple_strtoul(param, NULL, 10);
5325 rc = nodemap_set_allow_root(nodemap_name, bool_switch);
5327 case LCFG_NODEMAP_DENY_UNKNOWN:
5328 bool_switch = simple_strtoul(param, NULL, 10);
5329 rc = nodemap_set_deny_unknown(nodemap_name, bool_switch);
5331 case LCFG_NODEMAP_AUDIT_MODE:
5332 rc = kstrtoul(param, 10, (unsigned long *)&bool_switch);
5334 rc = nodemap_set_audit_mode(nodemap_name, bool_switch);
5336 case LCFG_NODEMAP_MAP_MODE:
5337 if (strcmp("both", param) == 0)
5338 rc = nodemap_set_mapping_mode(nodemap_name,
5340 else if (strcmp("uid_only", param) == 0)
5341 rc = nodemap_set_mapping_mode(nodemap_name,
5342 NODEMAP_MAP_UID_ONLY);
5343 else if (strcmp("gid_only", param) == 0)
5344 rc = nodemap_set_mapping_mode(nodemap_name,
5345 NODEMAP_MAP_GID_ONLY);
5349 case LCFG_NODEMAP_TRUSTED:
5350 bool_switch = simple_strtoul(param, NULL, 10);
5351 rc = nodemap_set_trust_client_ids(nodemap_name, bool_switch);
5353 case LCFG_NODEMAP_SQUASH_UID:
5354 int_id = simple_strtoul(param, NULL, 10);
5355 rc = nodemap_set_squash_uid(nodemap_name, int_id);
5357 case LCFG_NODEMAP_SQUASH_GID:
5358 int_id = simple_strtoul(param, NULL, 10);
5359 rc = nodemap_set_squash_gid(nodemap_name, int_id);
5361 case LCFG_NODEMAP_ADD_UIDMAP:
5362 case LCFG_NODEMAP_ADD_GIDMAP:
5363 rc = nodemap_parse_idmap(param, idmap);
5366 if (cmd == LCFG_NODEMAP_ADD_UIDMAP)
5367 rc = nodemap_add_idmap(nodemap_name, NODEMAP_UID,
5370 rc = nodemap_add_idmap(nodemap_name, NODEMAP_GID,
5373 case LCFG_NODEMAP_DEL_UIDMAP:
5374 case LCFG_NODEMAP_DEL_GIDMAP:
5375 rc = nodemap_parse_idmap(param, idmap);
5378 if (cmd == LCFG_NODEMAP_DEL_UIDMAP)
5379 rc = nodemap_del_idmap(nodemap_name, NODEMAP_UID,
5382 rc = nodemap_del_idmap(nodemap_name, NODEMAP_GID,
5385 case LCFG_NODEMAP_SET_FILESET:
5386 rc = nodemap_set_fileset(nodemap_name, param);
5395 int mgs_pool_cmd(const struct lu_env *env, struct mgs_device *mgs,
5396 enum lcfg_command_type cmd, char *fsname,
5397 char *poolname, char *ostname)
5402 char *label = NULL, *canceled_label = NULL;
5404 struct mgs_target_info *mti = NULL;
5405 bool checked = false;
5406 bool locked = false;
5411 rc = mgs_find_or_make_fsdb(env, mgs, fsname, &fsdb);
5413 CERROR("Can't get db for %s\n", fsname);
5416 if (test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
5417 CERROR("%s is not defined\n", fsname);
5419 GOTO(out_fsdb, rc = -EINVAL);
5422 label_sz = 10 + strlen(fsname) + strlen(poolname);
5424 /* check if ostname match fsname */
5425 if (ostname != NULL) {
5428 ptr = strrchr(ostname, '-');
5429 if ((ptr == NULL) ||
5430 (strncmp(fsname, ostname, ptr-ostname) != 0))
5432 label_sz += strlen(ostname);
5435 OBD_ALLOC(label, label_sz);
5437 GOTO(out_fsdb, rc = -ENOMEM);
5442 "new %s.%s", fsname, poolname);
5446 "add %s.%s.%s", fsname, poolname, ostname);
5449 OBD_ALLOC(canceled_label, label_sz);
5450 if (canceled_label == NULL)
5451 GOTO(out_label, rc = -ENOMEM);
5453 "rem %s.%s.%s", fsname, poolname, ostname);
5454 sprintf(canceled_label,
5455 "add %s.%s.%s", fsname, poolname, ostname);
5458 OBD_ALLOC(canceled_label, label_sz);
5459 if (canceled_label == NULL)
5460 GOTO(out_label, rc = -ENOMEM);
5462 "del %s.%s", fsname, poolname);
5463 sprintf(canceled_label,
5464 "new %s.%s", fsname, poolname);
5472 GOTO(out_cancel, rc = -ENOMEM);
5473 strncpy(mti->mti_svname, "lov pool", sizeof(mti->mti_svname));
5475 mutex_lock(&fsdb->fsdb_mutex);
5477 /* write pool def to all MDT logs */
5478 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
5479 if (test_bit(i, fsdb->fsdb_mdt_index_map)) {
5480 rc = name_create_mdt_and_lov(&logname, &lovname,
5485 if (!checked && (canceled_label == NULL)) {
5486 rc = mgs_check_marker(env, mgs, fsdb, mti,
5487 logname, lovname, label);
5489 name_destroy(&logname);
5490 name_destroy(&lovname);
5492 rc = (rc == LLOG_PROC_BREAK ?
5497 if (canceled_label != NULL)
5498 rc = mgs_modify(env, mgs, fsdb, mti, logname,
5499 lovname, canceled_label,
5503 rc = mgs_write_log_pool(env, mgs, logname,
5507 name_destroy(&logname);
5508 name_destroy(&lovname);
5514 rc = name_create(&logname, fsname, "-client");
5518 if (!checked && (canceled_label == NULL)) {
5519 rc = mgs_check_marker(env, mgs, fsdb, mti, logname,
5520 fsdb->fsdb_clilov, label);
5522 name_destroy(&logname);
5523 GOTO(out_mti, rc = (rc == LLOG_PROC_BREAK ?
5527 if (canceled_label != NULL) {
5528 rc = mgs_modify(env, mgs, fsdb, mti, logname,
5529 fsdb->fsdb_clilov, canceled_label, CM_SKIP);
5531 name_destroy(&logname);
5536 rc = mgs_write_log_pool(env, mgs, logname, fsdb, fsdb->fsdb_clilov,
5537 cmd, fsname, poolname, ostname, label);
5538 mutex_unlock(&fsdb->fsdb_mutex);
5540 name_destroy(&logname);
5541 /* request for update */
5542 mgs_revoke_lock(mgs, fsdb, CONFIG_T_CONFIG);
5548 mutex_unlock(&fsdb->fsdb_mutex);
5552 if (canceled_label != NULL)
5553 OBD_FREE(canceled_label, label_sz);
5555 OBD_FREE(label, label_sz);
5558 mgs_unlink_fsdb(mgs, fsdb);
5559 mgs_put_fsdb(mgs, fsdb);