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);
980 /** This structure is passed to mgs_replace_handler */
981 struct mgs_replace_data {
982 /* Nids are replaced for this target device */
983 struct mgs_target_info target;
984 /* Temporary modified llog */
985 struct llog_handle *temp_llh;
986 enum replace_state state;
992 * Check: a) if block should be skipped
993 * b) is it target block
998 * \retval 0 should not to be skipped
999 * \retval 1 should to be skipped
1001 static int check_markers(struct lustre_cfg *lcfg,
1002 struct mgs_replace_data *mrd)
1004 struct cfg_marker *marker;
1006 /* Track markers. Find given device */
1007 if (lcfg->lcfg_command == LCFG_MARKER) {
1008 marker = lustre_cfg_buf(lcfg, 1);
1009 /* Clean llog from records marked as CM_SKIP.
1010 CM_EXCLUDE records are used for "active" command
1011 and can be restored if needed */
1012 if ((marker->cm_flags & (CM_SKIP | CM_START)) ==
1013 (CM_SKIP | CM_START)) {
1014 mrd->state = REPLACE_SKIP;
1018 if ((marker->cm_flags & (CM_SKIP | CM_END)) ==
1019 (CM_SKIP | CM_END)) {
1020 mrd->state = REPLACE_COPY;
1024 if (strcmp(mrd->target.mti_svname, marker->cm_tgtname) == 0) {
1025 LASSERT(!(marker->cm_flags & CM_START) ||
1026 !(marker->cm_flags & CM_END));
1027 if (marker->cm_flags & CM_START) {
1028 mrd->state = REPLACE_UUID;
1029 mrd->failover = NULL;
1030 } else if (marker->cm_flags & CM_END)
1031 mrd->state = REPLACE_COPY;
1038 static int record_base(const struct lu_env *env, struct llog_handle *llh,
1039 char *cfgname, lnet_nid_t nid, int cmd,
1040 char *s1, char *s2, char *s3, char *s4)
1042 struct mgs_thread_info *mgi = mgs_env_info(env);
1043 struct llog_cfg_rec *lcr;
1046 CDEBUG(D_MGS, "lcfg %s %#x %s %s %s %s\n", cfgname,
1047 cmd, s1, s2, s3, s4);
1049 lustre_cfg_bufs_reset(&mgi->mgi_bufs, cfgname);
1051 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, s1);
1053 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 2, s2);
1055 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 3, s3);
1057 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 4, s4);
1059 lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
1063 lcr->lcr_cfg.lcfg_nid = nid;
1064 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1066 lustre_cfg_rec_free(lcr);
1070 "failed to write lcfg %s %#x %s %s %s %s: rc = %d\n",
1071 cfgname, cmd, s1, s2, s3, s4, rc);
1075 static inline int record_add_uuid(const struct lu_env *env,
1076 struct llog_handle *llh,
1077 uint64_t nid, char *uuid)
1079 return record_base(env, llh, NULL, nid, LCFG_ADD_UUID, uuid,
1083 static inline int record_add_conn(const struct lu_env *env,
1084 struct llog_handle *llh,
1085 char *devname, char *uuid)
1087 return record_base(env, llh, devname, 0, LCFG_ADD_CONN, uuid,
1091 static inline int record_attach(const struct lu_env *env,
1092 struct llog_handle *llh, char *devname,
1093 char *type, char *uuid)
1095 return record_base(env, llh, devname, 0, LCFG_ATTACH, type, uuid,
1099 static inline int record_setup(const struct lu_env *env,
1100 struct llog_handle *llh, char *devname,
1101 char *s1, char *s2, char *s3, char *s4)
1103 return record_base(env, llh, devname, 0, LCFG_SETUP, s1, s2, s3, s4);
1107 * \retval <0 record processing error
1108 * \retval n record is processed. No need copy original one.
1109 * \retval 0 record is not processed.
1111 static int process_command(const struct lu_env *env, struct lustre_cfg *lcfg,
1112 struct mgs_replace_data *mrd)
1119 if (mrd->state == REPLACE_UUID &&
1120 lcfg->lcfg_command == LCFG_ADD_UUID) {
1121 /* LCFG_ADD_UUID command found. Let's skip original command
1122 and add passed nids */
1123 ptr = mrd->target.mti_params;
1124 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
1125 if (!mrd->nodeuuid) {
1126 rc = name_create(&mrd->nodeuuid,
1127 libcfs_nid2str(nid), "");
1129 CERROR("Can't create uuid for "
1130 "nid %s, device %s\n",
1131 libcfs_nid2str(nid),
1132 mrd->target.mti_svname);
1136 CDEBUG(D_MGS, "add nid %s with uuid %s, "
1137 "device %s\n", libcfs_nid2str(nid),
1138 mrd->target.mti_params,
1140 rc = record_add_uuid(env,
1147 mrd->failover = ptr;
1152 if (nids_added == 0) {
1153 CERROR("No new nids were added, nid %s with uuid %s, "
1154 "device %s\n", libcfs_nid2str(nid),
1155 mrd->nodeuuid ? mrd->nodeuuid : "NULL",
1156 mrd->target.mti_svname);
1157 name_destroy(&mrd->nodeuuid);
1160 mrd->state = REPLACE_SETUP;
1166 if (mrd->state == REPLACE_SETUP && lcfg->lcfg_command == LCFG_SETUP) {
1167 /* LCFG_SETUP command found. UUID should be changed */
1168 rc = record_setup(env,
1170 /* devname the same */
1171 lustre_cfg_string(lcfg, 0),
1172 /* s1 is not changed */
1173 lustre_cfg_string(lcfg, 1),
1175 /* s3 is not changed */
1176 lustre_cfg_string(lcfg, 3),
1177 /* s4 is not changed */
1178 lustre_cfg_string(lcfg, 4));
1180 name_destroy(&mrd->nodeuuid);
1184 if (mrd->failover) {
1185 ptr = mrd->failover;
1186 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
1187 if (mrd->nodeuuid == NULL) {
1188 rc = name_create(&mrd->nodeuuid,
1189 libcfs_nid2str(nid),
1195 CDEBUG(D_MGS, "add nid %s for failover %s\n",
1196 libcfs_nid2str(nid), mrd->nodeuuid);
1197 rc = record_add_uuid(env, mrd->temp_llh, nid,
1200 name_destroy(&mrd->nodeuuid);
1204 rc = record_add_conn(env,
1206 lustre_cfg_string(lcfg, 0),
1208 name_destroy(&mrd->nodeuuid);
1213 if (mrd->nodeuuid) {
1214 rc = record_add_conn(env, mrd->temp_llh,
1215 lustre_cfg_string(lcfg, 0),
1217 name_destroy(&mrd->nodeuuid);
1222 mrd->state = REPLACE_DONE;
1226 /* Another commands in target device block */
1231 * Handler that called for every record in llog.
1232 * Records are processed in order they placed in llog.
1234 * \param[in] llh log to be processed
1235 * \param[in] rec current record
1236 * \param[in] data mgs_replace_data structure
1240 static int mgs_replace_nids_handler(const struct lu_env *env,
1241 struct llog_handle *llh,
1242 struct llog_rec_hdr *rec,
1245 struct mgs_replace_data *mrd;
1246 struct lustre_cfg *lcfg = REC_DATA(rec);
1247 int cfg_len = REC_DATA_LEN(rec);
1251 mrd = (struct mgs_replace_data *)data;
1253 if (rec->lrh_type != OBD_CFG_REC) {
1254 CERROR("unhandled lrh_type: %#x, cmd %x %s %s\n",
1255 rec->lrh_type, lcfg->lcfg_command,
1256 lustre_cfg_string(lcfg, 0),
1257 lustre_cfg_string(lcfg, 1));
1261 rc = lustre_cfg_sanity_check(lcfg, cfg_len);
1263 /* Do not copy any invalidated records */
1264 GOTO(skip_out, rc = 0);
1267 rc = check_markers(lcfg, mrd);
1268 if (rc || mrd->state == REPLACE_SKIP)
1269 GOTO(skip_out, rc = 0);
1271 /* Write to new log all commands outside target device block */
1272 if (mrd->state == REPLACE_COPY)
1273 GOTO(copy_out, rc = 0);
1275 if (mrd->state == REPLACE_DONE &&
1276 (lcfg->lcfg_command == LCFG_ADD_UUID ||
1277 lcfg->lcfg_command == LCFG_ADD_CONN)) {
1279 CWARN("Previous failover is deleted, but new one is "
1280 "not set. This means you configure system "
1281 "without failover or passed wrong replace_nids "
1282 "command parameters. Device %s, passed nids %s\n",
1283 mrd->target.mti_svname, mrd->target.mti_params);
1284 GOTO(skip_out, rc = 0);
1287 rc = process_command(env, lcfg, mrd);
1294 /* Record is placed in temporary llog as is */
1295 rc = llog_write(env, mrd->temp_llh, rec, LLOG_NEXT_IDX);
1297 CDEBUG(D_MGS, "Copied idx=%d, rc=%d, len=%d, cmd %x %s %s\n",
1298 rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
1299 lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
1303 CDEBUG(D_MGS, "Skipped idx=%d, rc=%d, len=%d, cmd %x %s %s\n",
1304 rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
1305 lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
1309 static int mgs_log_is_empty(const struct lu_env *env,
1310 struct mgs_device *mgs, char *name)
1312 struct llog_ctxt *ctxt;
1315 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
1316 LASSERT(ctxt != NULL);
1318 rc = llog_is_empty(env, ctxt, name);
1319 llog_ctxt_put(ctxt);
1323 static int mgs_replace_log(const struct lu_env *env,
1324 struct obd_device *mgs,
1325 char *logname, char *devname,
1326 llog_cb_t replace_handler, void *data)
1328 struct llog_handle *orig_llh, *backup_llh;
1329 struct llog_ctxt *ctxt;
1330 struct mgs_replace_data *mrd;
1331 struct mgs_device *mgs_dev = lu2mgs_dev(mgs->obd_lu_dev);
1332 static struct obd_uuid cfg_uuid = { .uuid = "config_uuid" };
1334 int rc, rc2, buf_size;
1338 ctxt = llog_get_context(mgs, LLOG_CONFIG_ORIG_CTXT);
1339 LASSERT(ctxt != NULL);
1341 if (mgs_log_is_empty(env, mgs_dev, logname)) {
1342 /* Log is empty. Nothing to replace */
1343 GOTO(out_put, rc = 0);
1346 now = ktime_get_real_seconds();
1348 /* max time64_t in decimal fits into 20 bytes long string */
1349 buf_size = strlen(logname) + 1 + 20 + 1 + strlen(".bak") + 1;
1350 OBD_ALLOC(backup, buf_size);
1352 GOTO(out_put, rc = -ENOMEM);
1354 snprintf(backup, buf_size, "%s.%llu.bak", logname, now);
1356 rc = llog_backup(env, mgs, ctxt, ctxt, logname, backup);
1358 /* Now erase original log file. Connections are not allowed.
1359 Backup is already saved */
1360 rc = llog_erase(env, ctxt, NULL, logname);
1363 } else if (rc != -ENOENT) {
1364 CERROR("%s: can't make backup for %s: rc = %d\n",
1365 mgs->obd_name, logname, rc);
1369 /* open local log */
1370 rc = llog_open_create(env, ctxt, &orig_llh, NULL, logname);
1372 GOTO(out_restore, rc);
1374 rc = llog_init_handle(env, orig_llh, LLOG_F_IS_PLAIN, &cfg_uuid);
1376 GOTO(out_closel, rc);
1378 /* open backup llog */
1379 rc = llog_open(env, ctxt, &backup_llh, NULL, backup,
1382 GOTO(out_closel, rc);
1384 rc = llog_init_handle(env, backup_llh, LLOG_F_IS_PLAIN, NULL);
1386 GOTO(out_close, rc);
1388 if (llog_get_size(backup_llh) <= 1)
1389 GOTO(out_close, rc = 0);
1393 GOTO(out_close, rc = -ENOMEM);
1394 /* devname is only needed information to replace UUID records */
1396 strlcpy(mrd->target.mti_svname, devname,
1397 sizeof(mrd->target.mti_svname));
1398 /* data is parsed in llog callback */
1400 strlcpy(mrd->target.mti_params, data,
1401 sizeof(mrd->target.mti_params));
1402 /* Copy records to this temporary llog */
1403 mrd->temp_llh = orig_llh;
1405 rc = llog_process(env, backup_llh, replace_handler,
1409 rc2 = llog_close(NULL, backup_llh);
1413 rc2 = llog_close(NULL, orig_llh);
1419 CERROR("%s: llog should be restored: rc = %d\n",
1421 rc2 = llog_backup(env, mgs, ctxt, ctxt, backup,
1424 CERROR("%s: can't restore backup %s: rc = %d\n",
1425 mgs->obd_name, logname, rc2);
1429 OBD_FREE(backup, buf_size);
1432 llog_ctxt_put(ctxt);
1435 CERROR("%s: failed to replace log %s: rc = %d\n",
1436 mgs->obd_name, logname, rc);
1441 static int mgs_replace_nids_log(const struct lu_env *env,
1442 struct obd_device *obd,
1443 char *logname, char *devname, char *nids)
1445 CDEBUG(D_MGS, "Replace NIDs for %s in %s\n", devname, logname);
1446 return mgs_replace_log(env, obd, logname, devname,
1447 mgs_replace_nids_handler, nids);
1451 * Parse device name and get file system name and/or device index
1453 * @devname device name (ex. lustre-MDT0000)
1454 * @fsname file system name extracted from @devname and returned
1455 * to the caller (optional)
1456 * @index device index extracted from @devname and returned to
1457 * the caller (optional)
1459 * RETURN 0 success if we are only interested in
1460 * extracting fsname from devname.
1463 * LDD_F_SV_TYPE_* Besides extracting the fsname the
1464 * user also wants the index. Report to
1465 * the user the type of obd device the
1466 * returned index belongs too.
1468 * -EINVAL The obd device name is improper so
1469 * fsname could not be extracted.
1471 * -ENXIO Failed to extract the index out of
1472 * the obd device name. Most likely an
1473 * invalid obd device name
1475 static int mgs_parse_devname(char *devname, char *fsname, u32 *index)
1480 /* Extract fsname */
1482 rc = server_name2fsname(devname, fsname, NULL);
1484 CDEBUG(D_MGS, "Device name %s without fsname\n",
1491 rc = server_name2index(devname, index, NULL);
1493 CDEBUG(D_MGS, "Device name %s with wrong index\n",
1499 /* server_name2index can return LDD_F_SV_TYPE_* so always return rc */
1503 /* This is only called during replace_nids */
1504 static int only_mgs_is_running(struct obd_device *mgs_obd)
1506 /* TDB: Is global variable with devices count exists? */
1507 int num_devices = get_devices_count();
1508 int num_exports = 0;
1509 struct obd_export *exp;
1511 spin_lock(&mgs_obd->obd_dev_lock);
1512 list_for_each_entry(exp, &mgs_obd->obd_exports, exp_obd_chain) {
1513 /* skip self export */
1514 if (exp == mgs_obd->obd_self_export)
1519 if (num_exports > 1)
1520 CERROR("%s: node %s still connected during replace_nids connect_flags:%llx\n",
1522 libcfs_nid2str(exp->exp_nid_stats->nid),
1523 exp_connect_flags(exp));
1525 spin_unlock(&mgs_obd->obd_dev_lock);
1527 /* osd, MGS and MGC + MGC export (nosvc starts MGC)
1528 * (wc -l /proc/fs/lustre/devices <= 3) && (non self exports == 1)
1530 return (num_devices <= 3) && (num_exports <= 1);
1533 static int name_create_mdt(char **logname, char *fsname, int mdt_idx)
1537 if (mdt_idx > INDEX_MAP_MAX_VALUE)
1540 snprintf(postfix, sizeof(postfix), "-MDT%04x", mdt_idx);
1541 return name_create(logname, fsname, postfix);
1545 * Replace nids for \a device to \a nids values
1547 * \param obd MGS obd device
1548 * \param devname nids need to be replaced for this device
1549 * (ex. lustre-OST0000)
1550 * \param nids nids list (ex. nid1,nid2,nid3)
1554 int mgs_replace_nids(const struct lu_env *env,
1555 struct mgs_device *mgs,
1556 char *devname, char *nids)
1558 /* Assume fsname is part of device name */
1559 char fsname[MTI_NAME_MAXLEN];
1563 struct fs_db *fsdb = NULL;
1566 struct obd_device *mgs_obd = mgs->mgs_obd;
1569 /* We can only change NIDs if no other nodes are connected */
1570 spin_lock(&mgs_obd->obd_dev_lock);
1571 conn_state = mgs_obd->obd_no_conn;
1572 mgs_obd->obd_no_conn = 1;
1573 spin_unlock(&mgs_obd->obd_dev_lock);
1575 /* We can not change nids if not only MGS is started */
1576 if (!only_mgs_is_running(mgs_obd)) {
1577 CERROR("Only MGS is allowed to be started\n");
1578 GOTO(out, rc = -EINPROGRESS);
1581 /* Get fsname and index */
1582 rc = mgs_parse_devname(devname, fsname, &index);
1586 rc = mgs_find_or_make_fsdb(env, mgs, fsname, &fsdb);
1588 CERROR("%s: can't find fsdb: rc = %d\n", fsname, rc);
1592 /* Process client llogs */
1593 name_create(&logname, fsname, "-client");
1594 rc = mgs_replace_nids_log(env, mgs_obd, logname, devname, nids);
1595 name_destroy(&logname);
1597 CERROR("%s: error while replacing NIDs for %s: rc = %d\n",
1598 fsname, devname, rc);
1602 /* Process MDT llogs */
1603 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
1604 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
1606 name_create_mdt(&logname, fsname, i);
1607 rc = mgs_replace_nids_log(env, mgs_obd, logname, devname, nids);
1608 name_destroy(&logname);
1614 spin_lock(&mgs_obd->obd_dev_lock);
1615 mgs_obd->obd_no_conn = conn_state;
1616 spin_unlock(&mgs_obd->obd_dev_lock);
1619 mgs_put_fsdb(mgs, fsdb);
1625 * This is called for every record in llog. Some of records are
1626 * skipped, others are copied to new log as is.
1627 * Records to be skipped are
1628 * marker records marked SKIP
1629 * records enclosed between SKIP markers
1631 * \param[in] llh log to be processed
1632 * \param[in] rec current record
1633 * \param[in] data mgs_replace_data structure
1637 static int mgs_clear_config_handler(const struct lu_env *env,
1638 struct llog_handle *llh,
1639 struct llog_rec_hdr *rec, void *data)
1641 struct mgs_replace_data *mrd;
1642 struct lustre_cfg *lcfg = REC_DATA(rec);
1643 int cfg_len = REC_DATA_LEN(rec);
1648 mrd = (struct mgs_replace_data *)data;
1650 if (rec->lrh_type != OBD_CFG_REC) {
1651 CDEBUG(D_MGS, "Config llog Name=%s, Record Index=%u, "
1652 "Unhandled Record Type=%#x\n", llh->lgh_name,
1653 rec->lrh_index, rec->lrh_type);
1657 rc = lustre_cfg_sanity_check(lcfg, cfg_len);
1659 CDEBUG(D_MGS, "Config llog Name=%s, Invalid config file.",
1664 if (lcfg->lcfg_command == LCFG_MARKER) {
1665 struct cfg_marker *marker;
1667 marker = lustre_cfg_buf(lcfg, 1);
1668 if (marker->cm_flags & CM_SKIP) {
1669 if (marker->cm_flags & CM_START)
1670 mrd->state = REPLACE_SKIP;
1671 if (marker->cm_flags & CM_END)
1672 mrd->state = REPLACE_COPY;
1673 /* SKIP section started or finished */
1674 CDEBUG(D_MGS, "Skip idx=%d, rc=%d, len=%d, "
1675 "cmd %x %s %s\n", rec->lrh_index, rc,
1676 rec->lrh_len, lcfg->lcfg_command,
1677 lustre_cfg_string(lcfg, 0),
1678 lustre_cfg_string(lcfg, 1));
1682 if (mrd->state == REPLACE_SKIP) {
1683 /* record enclosed between SKIP markers, skip it */
1684 CDEBUG(D_MGS, "Skip idx=%d, rc=%d, len=%d, "
1685 "cmd %x %s %s\n", rec->lrh_index, rc,
1686 rec->lrh_len, lcfg->lcfg_command,
1687 lustre_cfg_string(lcfg, 0),
1688 lustre_cfg_string(lcfg, 1));
1693 /* Record is placed in temporary llog as is */
1694 rc = llog_write(env, mrd->temp_llh, rec, LLOG_NEXT_IDX);
1696 CDEBUG(D_MGS, "Copied idx=%d, rc=%d, len=%d, cmd %x %s %s\n",
1697 rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
1698 lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
1703 * Directory CONFIGS/ may contain files which are not config logs to
1704 * be cleared. Skip any llogs with a non-alphanumeric character after
1705 * the last '-'. For example, fsname-MDT0000.sav, fsname-MDT0000.bak,
1706 * fsname-MDT0000.orig, fsname-MDT0000~, fsname-MDT0000.20150516, etc.
1708 static bool config_to_clear(const char *logname)
1713 str = strrchr(logname, '-');
1718 while (isalnum(str[++i]));
1719 return str[i] == '\0';
1723 * Clear config logs for \a name
1726 * \param mgs MGS device
1727 * \param name name of device or of filesystem
1728 * (ex. lustre-OST0000 or lustre) in later case all logs
1733 int mgs_clear_configs(const struct lu_env *env,
1734 struct mgs_device *mgs, const char *name)
1736 struct list_head dentry_list;
1737 struct mgs_direntry *dirent, *n;
1740 struct obd_device *mgs_obd = mgs->mgs_obd;
1745 /* Prevent clients and servers from connecting to mgs */
1746 spin_lock(&mgs_obd->obd_dev_lock);
1747 conn_state = mgs_obd->obd_no_conn;
1748 mgs_obd->obd_no_conn = 1;
1749 spin_unlock(&mgs_obd->obd_dev_lock);
1752 * config logs cannot be cleaned if anything other than
1755 if (!only_mgs_is_running(mgs_obd)) {
1756 CERROR("Only MGS is allowed to be started\n");
1757 GOTO(out, rc = -EBUSY);
1760 /* Find all the logs in the CONFIGS directory */
1761 rc = class_dentry_readdir(env, mgs, &dentry_list);
1763 CERROR("%s: cannot read config directory '%s': rc = %d\n",
1764 mgs_obd->obd_name, MOUNT_CONFIGS_DIR, rc);
1768 if (list_empty(&dentry_list)) {
1769 CERROR("%s: list empty reading config dir '%s': rc = %d\n",
1770 mgs_obd->obd_name, MOUNT_CONFIGS_DIR, -ENOENT);
1771 GOTO(out, rc = -ENOENT);
1774 OBD_ALLOC(namedash, strlen(name) + 2);
1775 if (namedash == NULL)
1776 GOTO(out, rc = -ENOMEM);
1777 snprintf(namedash, strlen(name) + 2, "%s-", name);
1779 list_for_each_entry(dirent, &dentry_list, mde_list) {
1780 if (strcmp(name, dirent->mde_name) &&
1781 strncmp(namedash, dirent->mde_name, strlen(namedash)))
1783 if (!config_to_clear(dirent->mde_name))
1785 CDEBUG(D_MGS, "%s: Clear config log %s\n",
1786 mgs_obd->obd_name, dirent->mde_name);
1787 rc = mgs_replace_log(env, mgs_obd, dirent->mde_name, NULL,
1788 mgs_clear_config_handler, NULL);
1793 list_for_each_entry_safe(dirent, n, &dentry_list, mde_list) {
1794 list_del_init(&dirent->mde_list);
1795 mgs_direntry_free(dirent);
1797 OBD_FREE(namedash, strlen(name) + 2);
1799 spin_lock(&mgs_obd->obd_dev_lock);
1800 mgs_obd->obd_no_conn = conn_state;
1801 spin_unlock(&mgs_obd->obd_dev_lock);
1806 static int record_lov_setup(const struct lu_env *env, struct llog_handle *llh,
1807 char *devname, struct lov_desc *desc)
1809 struct mgs_thread_info *mgi = mgs_env_info(env);
1810 struct llog_cfg_rec *lcr;
1813 lustre_cfg_bufs_reset(&mgi->mgi_bufs, devname);
1814 lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, desc, sizeof(*desc));
1815 lcr = lustre_cfg_rec_new(LCFG_SETUP, &mgi->mgi_bufs);
1819 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1820 lustre_cfg_rec_free(lcr);
1824 static int record_lmv_setup(const struct lu_env *env, struct llog_handle *llh,
1825 char *devname, struct lmv_desc *desc)
1827 struct mgs_thread_info *mgi = mgs_env_info(env);
1828 struct llog_cfg_rec *lcr;
1831 lustre_cfg_bufs_reset(&mgi->mgi_bufs, devname);
1832 lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, desc, sizeof(*desc));
1833 lcr = lustre_cfg_rec_new(LCFG_SETUP, &mgi->mgi_bufs);
1837 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1838 lustre_cfg_rec_free(lcr);
1842 static inline int record_mdc_add(const struct lu_env *env,
1843 struct llog_handle *llh,
1844 char *logname, char *mdcuuid,
1845 char *mdtuuid, char *index,
1848 return record_base(env,llh,logname,0,LCFG_ADD_MDC,
1849 mdtuuid,index,gen,mdcuuid);
1852 static inline int record_lov_add(const struct lu_env *env,
1853 struct llog_handle *llh,
1854 char *lov_name, char *ost_uuid,
1855 char *index, char *gen)
1857 return record_base(env, llh, lov_name, 0, LCFG_LOV_ADD_OBD,
1858 ost_uuid, index, gen, NULL);
1861 static inline int record_mount_opt(const struct lu_env *env,
1862 struct llog_handle *llh,
1863 char *profile, char *lov_name,
1866 return record_base(env, llh, NULL, 0, LCFG_MOUNTOPT,
1867 profile, lov_name, mdc_name, NULL);
1870 static int record_marker(const struct lu_env *env,
1871 struct llog_handle *llh,
1872 struct fs_db *fsdb, __u32 flags,
1873 char *tgtname, char *comment)
1875 struct mgs_thread_info *mgi = mgs_env_info(env);
1876 struct llog_cfg_rec *lcr;
1880 if (flags & CM_START)
1882 mgi->mgi_marker.cm_step = fsdb->fsdb_gen;
1883 mgi->mgi_marker.cm_flags = flags;
1884 mgi->mgi_marker.cm_vers = LUSTRE_VERSION_CODE;
1885 cplen = strlcpy(mgi->mgi_marker.cm_tgtname, tgtname,
1886 sizeof(mgi->mgi_marker.cm_tgtname));
1887 if (cplen >= sizeof(mgi->mgi_marker.cm_tgtname))
1889 cplen = strlcpy(mgi->mgi_marker.cm_comment, comment,
1890 sizeof(mgi->mgi_marker.cm_comment));
1891 if (cplen >= sizeof(mgi->mgi_marker.cm_comment))
1893 mgi->mgi_marker.cm_createtime = ktime_get_real_seconds();
1894 mgi->mgi_marker.cm_canceltime = 0;
1895 lustre_cfg_bufs_reset(&mgi->mgi_bufs, NULL);
1896 lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, &mgi->mgi_marker,
1897 sizeof(mgi->mgi_marker));
1898 lcr = lustre_cfg_rec_new(LCFG_MARKER, &mgi->mgi_bufs);
1902 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1903 lustre_cfg_rec_free(lcr);
1907 static int record_start_log(const struct lu_env *env, struct mgs_device *mgs,
1908 struct llog_handle **llh, char *name)
1910 static struct obd_uuid cfg_uuid = { .uuid = "config_uuid" };
1911 struct llog_ctxt *ctxt;
1916 GOTO(out, rc = -EBUSY);
1918 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
1920 GOTO(out, rc = -ENODEV);
1921 LASSERT(ctxt->loc_obd == mgs->mgs_obd);
1923 rc = llog_open_create(env, ctxt, llh, NULL, name);
1926 rc = llog_init_handle(env, *llh, LLOG_F_IS_PLAIN, &cfg_uuid);
1928 llog_close(env, *llh);
1930 llog_ctxt_put(ctxt);
1933 CERROR("%s: can't start log %s: rc = %d\n",
1934 mgs->mgs_obd->obd_name, name, rc);
1940 static int record_end_log(const struct lu_env *env, struct llog_handle **llh)
1944 rc = llog_close(env, *llh);
1950 /******************** config "macros" *********************/
1952 /* write an lcfg directly into a log (with markers) */
1953 static int mgs_write_log_direct(const struct lu_env *env,
1954 struct mgs_device *mgs, struct fs_db *fsdb,
1955 char *logname, struct llog_cfg_rec *lcr,
1956 char *devname, char *comment)
1958 struct llog_handle *llh = NULL;
1963 rc = record_start_log(env, mgs, &llh, logname);
1967 /* FIXME These should be a single journal transaction */
1968 rc = record_marker(env, llh, fsdb, CM_START, devname, comment);
1971 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1974 rc = record_marker(env, llh, fsdb, CM_END, devname, comment);
1978 record_end_log(env, &llh);
1982 /* write the lcfg in all logs for the given fs */
1983 static int mgs_write_log_direct_all(const struct lu_env *env,
1984 struct mgs_device *mgs,
1986 struct mgs_target_info *mti,
1987 struct llog_cfg_rec *lcr, char *devname,
1988 char *comment, int server_only)
1990 struct list_head log_list;
1991 struct mgs_direntry *dirent, *n;
1992 char *fsname = mti->mti_fsname;
1993 int rc = 0, len = strlen(fsname);
1996 /* Find all the logs in the CONFIGS directory */
1997 rc = class_dentry_readdir(env, mgs, &log_list);
2001 /* Could use fsdb index maps instead of directory listing */
2002 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
2003 list_del_init(&dirent->mde_list);
2004 /* don't write to sptlrpc rule log */
2005 if (strstr(dirent->mde_name, "-sptlrpc") != NULL)
2008 /* caller wants write server logs only */
2009 if (server_only && strstr(dirent->mde_name, "-client") != NULL)
2012 if (strlen(dirent->mde_name) <= len ||
2013 strncmp(fsname, dirent->mde_name, len) != 0 ||
2014 dirent->mde_name[len] != '-')
2017 CDEBUG(D_MGS, "Changing log %s\n", dirent->mde_name);
2018 /* Erase any old settings of this same parameter */
2019 rc = mgs_modify(env, mgs, fsdb, mti, dirent->mde_name,
2020 devname, comment, CM_SKIP);
2022 CERROR("%s: Can't modify llog %s: rc = %d\n",
2023 mgs->mgs_obd->obd_name, dirent->mde_name, rc);
2026 /* Write the new one */
2027 rc = mgs_write_log_direct(env, mgs, fsdb, dirent->mde_name,
2028 lcr, devname, comment);
2030 CERROR("%s: writing log %s: rc = %d\n",
2031 mgs->mgs_obd->obd_name, dirent->mde_name, rc);
2033 mgs_direntry_free(dirent);
2039 static int mgs_write_log_osp_to_mdt(const struct lu_env *env,
2040 struct mgs_device *mgs,
2042 struct mgs_target_info *mti,
2043 int index, char *logname);
2044 static int mgs_write_log_osc_to_lov(const struct lu_env *env,
2045 struct mgs_device *mgs,
2047 struct mgs_target_info *mti,
2048 char *logname, char *suffix, char *lovname,
2049 enum lustre_sec_part sec_part, int flags);
2050 static int name_create_mdt_and_lov(char **logname, char **lovname,
2051 struct fs_db *fsdb, int i);
2053 static int add_param(char *params, char *key, char *val)
2055 char *start = params + strlen(params);
2056 char *end = params + sizeof(((struct mgs_target_info *)0)->mti_params);
2060 keylen = strlen(key);
2061 if (start + 1 + keylen + strlen(val) >= end) {
2062 CERROR("params are too long: %s %s%s\n",
2063 params, key != NULL ? key : "", val);
2067 sprintf(start, " %s%s", key != NULL ? key : "", val);
2072 * Walk through client config log record and convert the related records
2075 static int mgs_steal_client_llog_handler(const struct lu_env *env,
2076 struct llog_handle *llh,
2077 struct llog_rec_hdr *rec, void *data)
2079 struct mgs_device *mgs;
2080 struct obd_device *obd;
2081 struct mgs_target_info *mti, *tmti;
2083 int cfg_len = rec->lrh_len;
2084 char *cfg_buf = (char*) (rec + 1);
2085 struct lustre_cfg *lcfg;
2087 struct llog_handle *mdt_llh = NULL;
2088 static int got_an_osc_or_mdc = 0;
2089 /* 0: not found any osc/mdc;
2093 static int last_step = -1;
2098 mti = ((struct temp_comp*)data)->comp_mti;
2099 tmti = ((struct temp_comp*)data)->comp_tmti;
2100 fsdb = ((struct temp_comp*)data)->comp_fsdb;
2101 obd = ((struct temp_comp *)data)->comp_obd;
2102 mgs = lu2mgs_dev(obd->obd_lu_dev);
2105 if (rec->lrh_type != OBD_CFG_REC) {
2106 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
2110 rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
2112 CERROR("Insane cfg\n");
2116 lcfg = (struct lustre_cfg *)cfg_buf;
2118 if (lcfg->lcfg_command == LCFG_MARKER) {
2119 struct cfg_marker *marker;
2120 marker = lustre_cfg_buf(lcfg, 1);
2121 if (!strncmp(marker->cm_comment, "add osc", 7) &&
2122 (marker->cm_flags & CM_START) &&
2123 !(marker->cm_flags & CM_SKIP)) {
2124 got_an_osc_or_mdc = 1;
2125 cplen = strlcpy(tmti->mti_svname, marker->cm_tgtname,
2126 sizeof(tmti->mti_svname));
2127 if (cplen >= sizeof(tmti->mti_svname))
2129 rc = record_start_log(env, mgs, &mdt_llh,
2133 rc = record_marker(env, mdt_llh, fsdb, CM_START,
2134 mti->mti_svname, "add osc(copied)");
2135 record_end_log(env, &mdt_llh);
2136 last_step = marker->cm_step;
2139 if (!strncmp(marker->cm_comment, "add osc", 7) &&
2140 (marker->cm_flags & CM_END) &&
2141 !(marker->cm_flags & CM_SKIP)) {
2142 LASSERT(last_step == marker->cm_step);
2144 got_an_osc_or_mdc = 0;
2145 memset(tmti, 0, sizeof(*tmti));
2146 rc = record_start_log(env, mgs, &mdt_llh,
2150 rc = record_marker(env, mdt_llh, fsdb, CM_END,
2151 mti->mti_svname, "add osc(copied)");
2152 record_end_log(env, &mdt_llh);
2155 if (!strncmp(marker->cm_comment, "add mdc", 7) &&
2156 (marker->cm_flags & CM_START) &&
2157 !(marker->cm_flags & CM_SKIP)) {
2158 got_an_osc_or_mdc = 2;
2159 last_step = marker->cm_step;
2160 memcpy(tmti->mti_svname, marker->cm_tgtname,
2161 strlen(marker->cm_tgtname));
2165 if (!strncmp(marker->cm_comment, "add mdc", 7) &&
2166 (marker->cm_flags & CM_END) &&
2167 !(marker->cm_flags & CM_SKIP)) {
2168 LASSERT(last_step == marker->cm_step);
2170 got_an_osc_or_mdc = 0;
2171 memset(tmti, 0, sizeof(*tmti));
2176 if (got_an_osc_or_mdc == 0 || last_step < 0)
2179 if (lcfg->lcfg_command == LCFG_ADD_UUID) {
2180 __u64 nodenid = lcfg->lcfg_nid;
2182 if (strlen(tmti->mti_uuid) == 0) {
2183 /* target uuid not set, this config record is before
2184 * LCFG_SETUP, this nid is one of target node nid.
2186 tmti->mti_nids[tmti->mti_nid_count] = nodenid;
2187 tmti->mti_nid_count++;
2189 char nidstr[LNET_NIDSTR_SIZE];
2191 /* failover node nid */
2192 libcfs_nid2str_r(nodenid, nidstr, sizeof(nidstr));
2193 rc = add_param(tmti->mti_params, PARAM_FAILNODE,
2200 if (lcfg->lcfg_command == LCFG_SETUP) {
2203 target = lustre_cfg_string(lcfg, 1);
2204 memcpy(tmti->mti_uuid, target, strlen(target));
2208 /* ignore client side sptlrpc_conf_log */
2209 if (lcfg->lcfg_command == LCFG_SPTLRPC_CONF)
2212 if (lcfg->lcfg_command == LCFG_ADD_MDC &&
2213 strstr(lustre_cfg_string(lcfg, 0), "-clilmv") != NULL) {
2216 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1)
2219 memcpy(tmti->mti_fsname, mti->mti_fsname,
2220 strlen(mti->mti_fsname));
2221 tmti->mti_stripe_index = index;
2223 rc = mgs_write_log_osp_to_mdt(env, mgs, fsdb, tmti,
2224 mti->mti_stripe_index,
2226 memset(tmti, 0, sizeof(*tmti));
2230 if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD) {
2233 char *logname, *lovname;
2235 rc = name_create_mdt_and_lov(&logname, &lovname, fsdb,
2236 mti->mti_stripe_index);
2239 sprintf(mdt_index, "-MDT%04x", mti->mti_stripe_index);
2241 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1) {
2242 name_destroy(&logname);
2243 name_destroy(&lovname);
2247 tmti->mti_stripe_index = index;
2248 rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, tmti, logname,
2251 name_destroy(&logname);
2252 name_destroy(&lovname);
2258 /* fsdb->fsdb_mutex is already held in mgs_write_log_target*/
2259 /* stealed from mgs_get_fsdb_from_llog*/
2260 static int mgs_steal_llog_for_mdt_from_client(const struct lu_env *env,
2261 struct mgs_device *mgs,
2263 struct temp_comp* comp)
2265 struct llog_handle *loghandle;
2266 struct mgs_target_info *tmti;
2267 struct llog_ctxt *ctxt;
2272 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
2273 LASSERT(ctxt != NULL);
2275 OBD_ALLOC_PTR(tmti);
2277 GOTO(out_ctxt, rc = -ENOMEM);
2279 comp->comp_tmti = tmti;
2280 comp->comp_obd = mgs->mgs_obd;
2282 rc = llog_open(env, ctxt, &loghandle, NULL, client_name,
2290 rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
2292 GOTO(out_close, rc);
2294 rc = llog_process_or_fork(env, loghandle, mgs_steal_client_llog_handler,
2295 (void *)comp, NULL, false);
2296 CDEBUG(D_MGS, "steal llog re = %d\n", rc);
2298 llog_close(env, loghandle);
2302 llog_ctxt_put(ctxt);
2306 /* lmv is the second thing for client logs */
2307 /* copied from mgs_write_log_lov. Please refer to that. */
2308 static int mgs_write_log_lmv(const struct lu_env *env,
2309 struct mgs_device *mgs,
2311 struct mgs_target_info *mti,
2312 char *logname, char *lmvname)
2314 struct llog_handle *llh = NULL;
2315 struct lmv_desc *lmvdesc;
2320 CDEBUG(D_MGS, "Writing lmv(%s) log for %s\n", lmvname,logname);
2322 OBD_ALLOC_PTR(lmvdesc);
2323 if (lmvdesc == NULL)
2325 lmvdesc->ld_active_tgt_count = 0;
2326 lmvdesc->ld_tgt_count = 0;
2327 sprintf((char*)lmvdesc->ld_uuid.uuid, "%s_UUID", lmvname);
2328 uuid = (char *)lmvdesc->ld_uuid.uuid;
2330 rc = record_start_log(env, mgs, &llh, logname);
2333 rc = record_marker(env, llh, fsdb, CM_START, lmvname, "lmv setup");
2336 rc = record_attach(env, llh, lmvname, "lmv", uuid);
2339 rc = record_lmv_setup(env, llh, lmvname, lmvdesc);
2342 rc = record_marker(env, llh, fsdb, CM_END, lmvname, "lmv setup");
2346 record_end_log(env, &llh);
2348 OBD_FREE_PTR(lmvdesc);
2352 /* lov is the first thing in the mdt and client logs */
2353 static int mgs_write_log_lov(const struct lu_env *env, struct mgs_device *mgs,
2354 struct fs_db *fsdb, struct mgs_target_info *mti,
2355 char *logname, char *lovname)
2357 struct llog_handle *llh = NULL;
2358 struct lov_desc *lovdesc;
2363 CDEBUG(D_MGS, "Writing lov(%s) log for %s\n", lovname, logname);
2366 #01 L attach 0:lov_mdsA 1:lov 2:71ccb_lov_mdsA_19f961a9e1
2367 #02 L lov_setup 0:lov_mdsA 1:(struct lov_desc)
2368 uuid=lov1_UUID, stripe count=1, size=1048576, offset=0, pattern=0
2371 /* FIXME just make lov_setup accept empty desc (put uuid in buf 2) */
2372 OBD_ALLOC_PTR(lovdesc);
2373 if (lovdesc == NULL)
2375 lovdesc->ld_magic = LOV_DESC_MAGIC;
2376 lovdesc->ld_tgt_count = 0;
2377 /* Defaults. Can be changed later by lcfg config_param */
2378 lovdesc->ld_default_stripe_count = 1;
2379 lovdesc->ld_pattern = LOV_PATTERN_RAID0;
2380 lovdesc->ld_default_stripe_size = LOV_DESC_STRIPE_SIZE_DEFAULT;
2381 lovdesc->ld_default_stripe_offset = -1;
2382 lovdesc->ld_qos_maxage = LOV_DESC_QOS_MAXAGE_DEFAULT;
2383 sprintf((char*)lovdesc->ld_uuid.uuid, "%s_UUID", lovname);
2384 /* can these be the same? */
2385 uuid = (char *)lovdesc->ld_uuid.uuid;
2387 /* This should always be the first entry in a log.
2388 rc = mgs_clear_log(obd, logname); */
2389 rc = record_start_log(env, mgs, &llh, logname);
2392 /* FIXME these should be a single journal transaction */
2393 rc = record_marker(env, llh, fsdb, CM_START, lovname, "lov setup");
2396 rc = record_attach(env, llh, lovname, "lov", uuid);
2399 rc = record_lov_setup(env, llh, lovname, lovdesc);
2402 rc = record_marker(env, llh, fsdb, CM_END, lovname, "lov setup");
2407 record_end_log(env, &llh);
2409 OBD_FREE_PTR(lovdesc);
2413 /* add failnids to open log */
2414 static int mgs_write_log_failnids(const struct lu_env *env,
2415 struct mgs_target_info *mti,
2416 struct llog_handle *llh,
2419 char *failnodeuuid = NULL;
2420 char *ptr = mti->mti_params;
2425 #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) nal=90 0: 1:uml1_UUID
2426 #04 L add_uuid nid=1@elan(0x1000000000001) nal=90 0: 1:uml1_UUID
2427 #05 L setup 0:OSC_uml1_ost1_mdsA 1:ost1_UUID 2:uml1_UUID
2428 #06 L add_uuid nid=uml2@tcp(0x20000c0a80202) nal=90 0: 1:uml2_UUID
2429 #0x L add_uuid nid=2@elan(0x1000000000002) nal=90 0: 1:uml2_UUID
2430 #07 L add_conn 0:OSC_uml1_ost1_mdsA 1:uml2_UUID
2434 * Pull failnid info out of params string, which may contain something
2435 * like "<nid1>,<nid2>:<nid3>,<nid4>". class_parse_nid() does not
2436 * complain about abnormal inputs like ",:<nid1>", "<nid1>:,<nid2>",
2437 * etc. However, convert_hostnames() should have caught those.
2439 while (class_find_param(ptr, PARAM_FAILNODE, &ptr) == 0) {
2440 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
2441 char nidstr[LNET_NIDSTR_SIZE];
2443 if (failnodeuuid == NULL) {
2444 /* We don't know the failover node name,
2445 * so just use the first nid as the uuid */
2446 libcfs_nid2str_r(nid, nidstr, sizeof(nidstr));
2447 rc = name_create(&failnodeuuid, nidstr, "");
2451 CDEBUG(D_MGS, "add nid %s for failover uuid %s, "
2453 libcfs_nid2str_r(nid, nidstr, sizeof(nidstr)),
2454 failnodeuuid, cliname);
2455 rc = record_add_uuid(env, llh, nid, failnodeuuid);
2457 * If *ptr is ':', we have added all NIDs for
2461 rc = record_add_conn(env, llh, cliname,
2463 name_destroy(&failnodeuuid);
2464 failnodeuuid = NULL;
2468 rc = record_add_conn(env, llh, cliname, failnodeuuid);
2469 name_destroy(&failnodeuuid);
2470 failnodeuuid = NULL;
2477 static int mgs_write_log_mdc_to_lmv(const struct lu_env *env,
2478 struct mgs_device *mgs,
2480 struct mgs_target_info *mti,
2481 char *logname, char *lmvname)
2483 struct llog_handle *llh = NULL;
2484 char *mdcname = NULL;
2485 char *nodeuuid = NULL;
2486 char *mdcuuid = NULL;
2487 char *lmvuuid = NULL;
2489 char nidstr[LNET_NIDSTR_SIZE];
2493 if (mgs_log_is_empty(env, mgs, logname)) {
2494 CERROR("log is empty! Logical error\n");
2498 CDEBUG(D_MGS, "adding mdc for %s to log %s:lmv(%s)\n",
2499 mti->mti_svname, logname, lmvname);
2501 libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2502 rc = name_create(&nodeuuid, nidstr, "");
2505 rc = name_create(&mdcname, mti->mti_svname, "-mdc");
2508 rc = name_create(&mdcuuid, mdcname, "_UUID");
2511 rc = name_create(&lmvuuid, lmvname, "_UUID");
2515 rc = record_start_log(env, mgs, &llh, logname);
2518 rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
2522 for (i = 0; i < mti->mti_nid_count; i++) {
2523 CDEBUG(D_MGS, "add nid %s for mdt\n",
2524 libcfs_nid2str_r(mti->mti_nids[i],
2525 nidstr, sizeof(nidstr)));
2527 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2532 rc = record_attach(env, llh, mdcname, LUSTRE_MDC_NAME, lmvuuid);
2535 rc = record_setup(env, llh, mdcname, mti->mti_uuid, nodeuuid,
2539 rc = mgs_write_log_failnids(env, mti, llh, mdcname);
2542 snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
2543 rc = record_mdc_add(env, llh, lmvname, mdcuuid, mti->mti_uuid,
2547 rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname,
2552 record_end_log(env, &llh);
2554 name_destroy(&lmvuuid);
2555 name_destroy(&mdcuuid);
2556 name_destroy(&mdcname);
2557 name_destroy(&nodeuuid);
2561 static inline int name_create_lov(char **lovname, char *mdtname,
2562 struct fs_db *fsdb, int index)
2565 if (index == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2566 return name_create(lovname, fsdb->fsdb_name, "-mdtlov");
2568 return name_create(lovname, mdtname, "-mdtlov");
2571 static int name_create_mdt_and_lov(char **logname, char **lovname,
2572 struct fs_db *fsdb, int i)
2576 rc = name_create_mdt(logname, fsdb->fsdb_name, i);
2580 if (i == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2581 rc = name_create(lovname, fsdb->fsdb_name, "-mdtlov");
2583 rc = name_create(lovname, *logname, "-mdtlov");
2585 name_destroy(logname);
2591 static inline int name_create_mdt_osc(char **oscname, char *ostname,
2592 struct fs_db *fsdb, int i)
2596 if (i == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2597 sprintf(suffix, "-osc");
2599 sprintf(suffix, "-osc-MDT%04x", i);
2600 return name_create(oscname, ostname, suffix);
2603 /* add new mdc to already existent MDS */
2604 static int mgs_write_log_osp_to_mdt(const struct lu_env *env,
2605 struct mgs_device *mgs,
2607 struct mgs_target_info *mti,
2608 int mdt_index, char *logname)
2610 struct llog_handle *llh = NULL;
2611 char *nodeuuid = NULL;
2612 char *ospname = NULL;
2613 char *lovuuid = NULL;
2614 char *mdtuuid = NULL;
2615 char *svname = NULL;
2616 char *mdtname = NULL;
2617 char *lovname = NULL;
2619 char nidstr[LNET_NIDSTR_SIZE];
2623 if (mgs_log_is_empty(env, mgs, mti->mti_svname)) {
2624 CERROR("log is empty! Logical error\n");
2628 CDEBUG(D_MGS, "adding osp index %d to %s\n", mti->mti_stripe_index,
2631 rc = name_create_mdt(&mdtname, fsdb->fsdb_name, mti->mti_stripe_index);
2635 libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2636 rc = name_create(&nodeuuid, nidstr, "");
2638 GOTO(out_destory, rc);
2640 rc = name_create(&svname, mdtname, "-osp");
2642 GOTO(out_destory, rc);
2644 sprintf(index_str, "-MDT%04x", mdt_index);
2645 rc = name_create(&ospname, svname, index_str);
2647 GOTO(out_destory, rc);
2649 rc = name_create_lov(&lovname, logname, fsdb, mdt_index);
2651 GOTO(out_destory, rc);
2653 rc = name_create(&lovuuid, lovname, "_UUID");
2655 GOTO(out_destory, rc);
2657 rc = name_create(&mdtuuid, mdtname, "_UUID");
2659 GOTO(out_destory, rc);
2661 rc = record_start_log(env, mgs, &llh, logname);
2663 GOTO(out_destory, rc);
2665 rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
2668 GOTO(out_destory, rc);
2670 for (i = 0; i < mti->mti_nid_count; i++) {
2671 CDEBUG(D_MGS, "add nid %s for mdt\n",
2672 libcfs_nid2str_r(mti->mti_nids[i],
2673 nidstr, sizeof(nidstr)));
2674 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2679 rc = record_attach(env, llh, ospname, LUSTRE_OSP_NAME, lovuuid);
2683 rc = record_setup(env, llh, ospname, mti->mti_uuid, nodeuuid,
2688 rc = mgs_write_log_failnids(env, mti, llh, ospname);
2692 /* Add mdc(osp) to lod */
2693 snprintf(index_str, sizeof(index_str), "%d", mti->mti_stripe_index);
2694 rc = record_base(env, llh, lovname, 0, LCFG_ADD_MDC, mti->mti_uuid,
2695 index_str, "1", NULL);
2699 rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname, "add osp");
2704 record_end_log(env, &llh);
2707 name_destroy(&mdtuuid);
2708 name_destroy(&lovuuid);
2709 name_destroy(&lovname);
2710 name_destroy(&ospname);
2711 name_destroy(&svname);
2712 name_destroy(&nodeuuid);
2713 name_destroy(&mdtname);
2717 static int mgs_write_log_mdt0(const struct lu_env *env,
2718 struct mgs_device *mgs,
2720 struct mgs_target_info *mti)
2722 char *log = mti->mti_svname;
2723 struct llog_handle *llh = NULL;
2724 char *uuid, *lovname;
2726 char *ptr = mti->mti_params;
2727 int rc = 0, failout = 0;
2730 OBD_ALLOC(uuid, sizeof(struct obd_uuid));
2734 if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
2735 failout = (strncmp(ptr, "failout", 7) == 0);
2737 rc = name_create(&lovname, log, "-mdtlov");
2740 if (mgs_log_is_empty(env, mgs, log)) {
2741 rc = mgs_write_log_lov(env, mgs, fsdb, mti, log, lovname);
2746 sprintf(mdt_index, "%d", mti->mti_stripe_index);
2748 rc = record_start_log(env, mgs, &llh, log);
2752 /* add MDT itself */
2754 /* FIXME this whole fn should be a single journal transaction */
2755 sprintf(uuid, "%s_UUID", log);
2756 rc = record_marker(env, llh, fsdb, CM_START, log, "add mdt");
2759 rc = record_attach(env, llh, log, LUSTRE_MDT_NAME, uuid);
2762 rc = record_mount_opt(env, llh, log, lovname, NULL);
2765 rc = record_setup(env, llh, log, uuid, mdt_index, lovname,
2766 failout ? "n" : "f");
2769 rc = record_marker(env, llh, fsdb, CM_END, log, "add mdt");
2773 record_end_log(env, &llh);
2775 name_destroy(&lovname);
2777 OBD_FREE(uuid, sizeof(struct obd_uuid));
2781 /* envelope method for all layers log */
2782 static int mgs_write_log_mdt(const struct lu_env *env,
2783 struct mgs_device *mgs,
2785 struct mgs_target_info *mti)
2787 struct mgs_thread_info *mgi = mgs_env_info(env);
2788 struct llog_handle *llh = NULL;
2793 CDEBUG(D_MGS, "writing new mdt %s\n", mti->mti_svname);
2795 if (mti->mti_uuid[0] == '\0') {
2796 /* Make up our own uuid */
2797 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
2798 "%s_UUID", mti->mti_svname);
2802 rc = mgs_write_log_mdt0(env, mgs, fsdb, mti);
2805 /* Append the mdt info to the client log */
2806 rc = name_create(&cliname, mti->mti_fsname, "-client");
2810 if (mgs_log_is_empty(env, mgs, cliname)) {
2811 /* Start client log */
2812 rc = mgs_write_log_lov(env, mgs, fsdb, mti, cliname,
2816 rc = mgs_write_log_lmv(env, mgs, fsdb, mti, cliname,
2823 #09 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0: 1:uml1_UUID
2824 #10 L attach 0:MDC_uml1_mdsA_MNT_client 1:mdc 2:1d834_MNT_client_03f
2825 #11 L setup 0:MDC_uml1_mdsA_MNT_client 1:mdsA_UUID 2:uml1_UUID
2826 #12 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0: 1:uml2_UUID
2827 #13 L add_conn 0:MDC_uml1_mdsA_MNT_client 1:uml2_UUID
2828 #14 L mount_option 0: 1:client 2:lov1 3:MDC_uml1_mdsA_MNT_client
2831 /* copy client info about lov/lmv */
2832 mgi->mgi_comp.comp_mti = mti;
2833 mgi->mgi_comp.comp_fsdb = fsdb;
2835 rc = mgs_steal_llog_for_mdt_from_client(env, mgs, cliname,
2839 rc = mgs_write_log_mdc_to_lmv(env, mgs, fsdb, mti, cliname,
2845 rc = record_start_log(env, mgs, &llh, cliname);
2849 rc = record_marker(env, llh, fsdb, CM_START, cliname, "mount opts");
2852 rc = record_mount_opt(env, llh, cliname, fsdb->fsdb_clilov,
2856 rc = record_marker(env, llh, fsdb, CM_END, cliname, "mount opts");
2860 /* for_all_existing_mdt except current one */
2861 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
2862 if (i != mti->mti_stripe_index &&
2863 test_bit(i, fsdb->fsdb_mdt_index_map)) {
2866 rc = name_create_mdt(&logname, fsdb->fsdb_name, i);
2870 /* NB: If the log for the MDT is empty, it means
2871 * the MDT is only added to the index
2872 * map, and not being process yet, i.e. this
2873 * is an unregistered MDT, see mgs_write_log_target().
2874 * so we should skip it. Otherwise
2876 * 1. MGS get register request for MDT1 and MDT2.
2878 * 2. Then both MDT1 and MDT2 are added into
2879 * fsdb_mdt_index_map. (see mgs_set_index()).
2881 * 3. Then MDT1 get the lock of fsdb_mutex, then
2882 * generate the config log, here, it will regard MDT2
2883 * as an existent MDT, and generate "add osp" for
2884 * lustre-MDT0001-osp-MDT0002. Note: at the moment
2885 * MDT0002 config log is still empty, so it will
2886 * add "add osp" even before "lov setup", which
2887 * will definitly cause trouble.
2889 * 4. MDT1 registeration finished, fsdb_mutex is
2890 * released, then MDT2 get in, then in above
2891 * mgs_steal_llog_for_mdt_from_client(), it will
2892 * add another osp log for lustre-MDT0001-osp-MDT0002,
2893 * which will cause another trouble.*/
2894 if (!mgs_log_is_empty(env, mgs, logname))
2895 rc = mgs_write_log_osp_to_mdt(env, mgs, fsdb,
2898 name_destroy(&logname);
2904 record_end_log(env, &llh);
2906 name_destroy(&cliname);
2910 /* Add the ost info to the client/mdt lov */
2911 static int mgs_write_log_osc_to_lov(const struct lu_env *env,
2912 struct mgs_device *mgs, struct fs_db *fsdb,
2913 struct mgs_target_info *mti,
2914 char *logname, char *suffix, char *lovname,
2915 enum lustre_sec_part sec_part, int flags)
2917 struct llog_handle *llh = NULL;
2918 char *nodeuuid = NULL;
2919 char *oscname = NULL;
2920 char *oscuuid = NULL;
2921 char *lovuuid = NULL;
2922 char *svname = NULL;
2924 char nidstr[LNET_NIDSTR_SIZE];
2928 CDEBUG(D_INFO, "adding osc for %s to log %s\n",
2929 mti->mti_svname, logname);
2931 if (mgs_log_is_empty(env, mgs, logname)) {
2932 CERROR("log is empty! Logical error\n");
2936 libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2937 rc = name_create(&nodeuuid, nidstr, "");
2940 rc = name_create(&svname, mti->mti_svname, "-osc");
2944 /* for the system upgraded from old 1.8, keep using the old osc naming
2945 * style for mdt, see name_create_mdt_osc(). LU-1257 */
2946 if (test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2947 rc = name_create(&oscname, svname, "");
2949 rc = name_create(&oscname, svname, suffix);
2953 rc = name_create(&oscuuid, oscname, "_UUID");
2956 rc = name_create(&lovuuid, lovname, "_UUID");
2962 #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0: 1:uml1_UUID
2964 #04 L add_uuid nid=1@elan(0x1000000000001) nal=90 0: 1:uml1_UUID
2965 #04 L attach 0:OSC_uml1_ost1_MNT_client 1:osc 2:89070_lov1_a41dff51a
2966 #05 L setup 0:OSC_uml1_ost1_MNT_client 1:ost1_UUID 2:uml1_UUID
2968 #06 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0: 1:uml2_UUID
2969 #07 L add_conn 0:OSC_uml1_ost1_MNT_client 1:uml2_UUID
2970 #08 L lov_modify_tgts add 0:lov1 1:ost1_UUID 2(index):0 3(gen):1
2973 rc = record_start_log(env, mgs, &llh, logname);
2977 /* FIXME these should be a single journal transaction */
2978 rc = record_marker(env, llh, fsdb, CM_START | flags, mti->mti_svname,
2983 /* NB: don't change record order, because upon MDT steal OSC config
2984 * from client, it treats all nids before LCFG_SETUP as target nids
2985 * (multiple interfaces), while nids after as failover node nids.
2986 * See mgs_steal_client_llog_handler() LCFG_ADD_UUID.
2988 for (i = 0; i < mti->mti_nid_count; i++) {
2989 CDEBUG(D_MGS, "add nid %s\n",
2990 libcfs_nid2str_r(mti->mti_nids[i],
2991 nidstr, sizeof(nidstr)));
2992 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2996 rc = record_attach(env, llh, oscname, LUSTRE_OSC_NAME, lovuuid);
2999 rc = record_setup(env, llh, oscname, mti->mti_uuid, nodeuuid,
3003 rc = mgs_write_log_failnids(env, mti, llh, oscname);
3007 snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
3009 rc = record_lov_add(env, llh, lovname, mti->mti_uuid, index, "1");
3012 rc = record_marker(env, llh, fsdb, CM_END | flags, mti->mti_svname,
3017 record_end_log(env, &llh);
3019 name_destroy(&lovuuid);
3020 name_destroy(&oscuuid);
3021 name_destroy(&oscname);
3022 name_destroy(&svname);
3023 name_destroy(&nodeuuid);
3027 static int mgs_write_log_ost(const struct lu_env *env,
3028 struct mgs_device *mgs, struct fs_db *fsdb,
3029 struct mgs_target_info *mti)
3031 struct llog_handle *llh = NULL;
3032 char *logname, *lovname;
3033 char *ptr = mti->mti_params;
3034 int rc, flags = 0, failout = 0, i;
3037 CDEBUG(D_MGS, "writing new ost %s\n", mti->mti_svname);
3039 /* The ost startup log */
3041 /* If the ost log already exists, that means that someone reformatted
3042 the ost and it called target_add again. */
3043 if (!mgs_log_is_empty(env, mgs, mti->mti_svname)) {
3044 LCONSOLE_ERROR_MSG(0x141, "The config log for %s already "
3045 "exists, yet the server claims it never "
3046 "registered. It may have been reformatted, "
3047 "or the index changed. writeconf the MDT to "
3048 "regenerate all logs.\n", mti->mti_svname);
3053 attach obdfilter ost1 ost1_UUID
3054 setup /dev/loop2 ldiskfs f|n errors=remount-ro,user_xattr
3056 if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
3057 failout = (strncmp(ptr, "failout", 7) == 0);
3058 rc = record_start_log(env, mgs, &llh, mti->mti_svname);
3061 /* FIXME these should be a single journal transaction */
3062 rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,"add ost");
3065 if (*mti->mti_uuid == '\0')
3066 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
3067 "%s_UUID", mti->mti_svname);
3068 rc = record_attach(env, llh, mti->mti_svname,
3069 "obdfilter"/*LUSTRE_OST_NAME*/, mti->mti_uuid);
3072 rc = record_setup(env, llh, mti->mti_svname,
3073 "dev"/*ignored*/, "type"/*ignored*/,
3074 failout ? "n" : "f", NULL/*options*/);
3077 rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname, "add ost");
3081 record_end_log(env, &llh);
3084 /* We also have to update the other logs where this osc is part of
3087 if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
3088 /* If we're upgrading, the old mdt log already has our
3089 entry. Let's do a fake one for fun. */
3090 /* Note that we can't add any new failnids, since we don't
3091 know the old osc names. */
3092 flags = CM_SKIP | CM_UPGRADE146;
3094 } else if ((mti->mti_flags & LDD_F_UPDATE) != LDD_F_UPDATE) {
3095 /* If the update flag isn't set, don't update client/mdt
3098 LCONSOLE_WARN("Client log for %s was not updated; writeconf "
3099 "the MDT first to regenerate it.\n",
3103 /* Add ost to all MDT lov defs */
3104 for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
3105 if (test_bit(i, fsdb->fsdb_mdt_index_map)) {
3108 rc = name_create_mdt_and_lov(&logname, &lovname, fsdb,
3113 snprintf(mdt_index, sizeof(mdt_index), "-MDT%04x", i);
3114 rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, mti,
3116 lovname, LUSTRE_SP_MDT,
3118 name_destroy(&logname);
3119 name_destroy(&lovname);
3125 /* Append ost info to the client log */
3126 rc = name_create(&logname, mti->mti_fsname, "-client");
3129 if (mgs_log_is_empty(env, mgs, logname)) {
3130 /* Start client log */
3131 rc = mgs_write_log_lov(env, mgs, fsdb, mti, logname,
3135 rc = mgs_write_log_lmv(env, mgs, fsdb, mti, logname,
3140 rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, mti, logname, "",
3141 fsdb->fsdb_clilov, LUSTRE_SP_CLI, flags);
3143 name_destroy(&logname);
3147 static __inline__ int mgs_param_empty(char *ptr)
3151 if ((tmp = strchr(ptr, '=')) && (*(++tmp) == '\0'))
3156 static int mgs_write_log_failnid_internal(const struct lu_env *env,
3157 struct mgs_device *mgs,
3159 struct mgs_target_info *mti,
3160 char *logname, char *cliname)
3163 struct llog_handle *llh = NULL;
3165 if (mgs_param_empty(mti->mti_params)) {
3166 /* Remove _all_ failnids */
3167 rc = mgs_modify(env, mgs, fsdb, mti, logname,
3168 mti->mti_svname, "add failnid", CM_SKIP);
3169 return rc < 0 ? rc : 0;
3172 /* Otherwise failover nids are additive */
3173 rc = record_start_log(env, mgs, &llh, logname);
3176 /* FIXME this should be a single journal transaction */
3177 rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
3181 rc = mgs_write_log_failnids(env, mti, llh, cliname);
3184 rc = record_marker(env, llh, fsdb, CM_END,
3185 mti->mti_svname, "add failnid");
3187 record_end_log(env, &llh);
3192 /* Add additional failnids to an existing log.
3193 The mdc/osc must have been added to logs first */
3194 /* tcp nids must be in dotted-quad ascii -
3195 we can't resolve hostnames from the kernel. */
3196 static int mgs_write_log_add_failnid(const struct lu_env *env,
3197 struct mgs_device *mgs,
3199 struct mgs_target_info *mti)
3201 char *logname, *cliname;
3205 /* FIXME we currently can't erase the failnids
3206 * given when a target first registers, since they aren't part of
3207 * an "add uuid" stanza
3210 /* Verify that we know about this target */
3211 if (mgs_log_is_empty(env, mgs, mti->mti_svname)) {
3212 LCONSOLE_ERROR_MSG(0x142, "The target %s has not registered "
3213 "yet. It must be started before failnids "
3214 "can be added.\n", mti->mti_svname);
3218 /* Create mdc/osc client name (e.g. lustre-OST0001-osc) */
3219 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
3220 rc = name_create(&cliname, mti->mti_svname, "-mdc");
3221 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
3222 rc = name_create(&cliname, mti->mti_svname, "-osc");
3229 /* Add failover nids to the client log */
3230 rc = name_create(&logname, mti->mti_fsname, "-client");
3232 name_destroy(&cliname);
3236 rc = mgs_write_log_failnid_internal(env, mgs, fsdb,mti,logname,cliname);
3237 name_destroy(&logname);
3238 name_destroy(&cliname);
3242 if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
3243 /* Add OST failover nids to the MDT logs as well */
3246 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
3247 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
3249 rc = name_create_mdt(&logname, mti->mti_fsname, i);
3252 rc = name_create_mdt_osc(&cliname, mti->mti_svname,
3255 name_destroy(&logname);
3258 rc = mgs_write_log_failnid_internal(env, mgs, fsdb,
3261 name_destroy(&cliname);
3262 name_destroy(&logname);
3271 static int mgs_wlp_lcfg(const struct lu_env *env,
3272 struct mgs_device *mgs, struct fs_db *fsdb,
3273 struct mgs_target_info *mti,
3274 char *logname, struct lustre_cfg_bufs *bufs,
3275 char *tgtname, char *ptr)
3277 char comment[MTI_NAME_MAXLEN];
3279 struct llog_cfg_rec *lcr;
3282 /* Erase any old settings of this same parameter */
3283 memcpy(comment, ptr, MTI_NAME_MAXLEN);
3284 comment[MTI_NAME_MAXLEN - 1] = 0;
3285 /* But don't try to match the value. */
3286 tmp = strchr(comment, '=');
3289 /* FIXME we should skip settings that are the same as old values */
3290 rc = mgs_modify(env, mgs, fsdb, mti, logname, tgtname, comment,CM_SKIP);
3293 del = mgs_param_empty(ptr);
3295 LCONSOLE_INFO("%s parameter %s.%s in log %s\n", del ? "Disabling" : rc ?
3296 "Setting" : "Modifying", tgtname, comment, logname);
3298 /* mgs_modify() will return 1 if nothing had to be done */
3304 lustre_cfg_bufs_reset(bufs, tgtname);
3305 lustre_cfg_bufs_set_string(bufs, 1, ptr);
3306 if (mti->mti_flags & LDD_F_PARAM2)
3307 lustre_cfg_bufs_set_string(bufs, 2, LCTL_UPCALL);
3309 lcr = lustre_cfg_rec_new((mti->mti_flags & LDD_F_PARAM2) ?
3310 LCFG_SET_PARAM : LCFG_PARAM, bufs);
3314 rc = mgs_write_log_direct(env, mgs, fsdb, logname, lcr, tgtname,
3316 lustre_cfg_rec_free(lcr);
3320 /* write global variable settings into log */
3321 static int mgs_write_log_sys(const struct lu_env *env,
3322 struct mgs_device *mgs, struct fs_db *fsdb,
3323 struct mgs_target_info *mti, char *sys, char *ptr)
3325 struct mgs_thread_info *mgi = mgs_env_info(env);
3326 struct lustre_cfg *lcfg;
3327 struct llog_cfg_rec *lcr;
3329 int rc, cmd, convert = 1;
3331 if (class_match_param(ptr, PARAM_TIMEOUT, &tmp) == 0) {
3332 cmd = LCFG_SET_TIMEOUT;
3333 } else if (class_match_param(ptr, PARAM_LDLM_TIMEOUT, &tmp) == 0) {
3334 cmd = LCFG_SET_LDLM_TIMEOUT;
3335 /* Check for known params here so we can return error to lctl */
3336 } else if ((class_match_param(ptr, PARAM_AT_MIN, &tmp) == 0) ||
3337 (class_match_param(ptr, PARAM_AT_MAX, &tmp) == 0) ||
3338 (class_match_param(ptr, PARAM_AT_EXTRA, &tmp) == 0) ||
3339 (class_match_param(ptr, PARAM_AT_EARLY_MARGIN, &tmp) == 0) ||
3340 (class_match_param(ptr, PARAM_AT_HISTORY, &tmp) == 0)) {
3342 } else if (class_match_param(ptr, PARAM_JOBID_VAR, &tmp) == 0) {
3343 convert = 0; /* Don't convert string value to integer */
3349 if (mgs_param_empty(ptr))
3350 CDEBUG(D_MGS, "global '%s' removed\n", sys);
3352 CDEBUG(D_MGS, "global '%s' val=%s\n", sys, tmp);
3354 lustre_cfg_bufs_reset(&mgi->mgi_bufs, NULL);
3355 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, sys);
3356 if (!convert && *tmp != '\0')
3357 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 2, tmp);
3358 lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
3362 lcfg = &lcr->lcr_cfg;
3363 lcfg->lcfg_num = convert ? simple_strtoul(tmp, NULL, 0) : 0;
3364 /* truncate the comment to the parameter name */
3368 /* modify all servers and clients */
3369 rc = mgs_write_log_direct_all(env, mgs, fsdb, mti,
3370 *tmp == '\0' ? NULL : lcr,
3371 mti->mti_fsname, sys, 0);
3372 if (rc == 0 && *tmp != '\0') {
3374 case LCFG_SET_TIMEOUT:
3375 if (!obd_timeout_set || lcfg->lcfg_num > obd_timeout)
3376 class_process_config(lcfg);
3378 case LCFG_SET_LDLM_TIMEOUT:
3379 if (!ldlm_timeout_set || lcfg->lcfg_num > ldlm_timeout)
3380 class_process_config(lcfg);
3387 lustre_cfg_rec_free(lcr);
3391 /* write quota settings into log */
3392 static int mgs_write_log_quota(const struct lu_env *env, struct mgs_device *mgs,
3393 struct fs_db *fsdb, struct mgs_target_info *mti,
3394 char *quota, char *ptr)
3396 struct mgs_thread_info *mgi = mgs_env_info(env);
3397 struct llog_cfg_rec *lcr;
3400 int rc, cmd = LCFG_PARAM;
3402 /* support only 'meta' and 'data' pools so far */
3403 if (class_match_param(ptr, QUOTA_METAPOOL_NAME, &tmp) != 0 &&
3404 class_match_param(ptr, QUOTA_DATAPOOL_NAME, &tmp) != 0) {
3405 CERROR("parameter quota.%s isn't supported (only quota.mdt "
3406 "& quota.ost are)\n", ptr);
3411 CDEBUG(D_MGS, "global '%s' removed\n", quota);
3413 CDEBUG(D_MGS, "global '%s'\n", quota);
3415 if (strchr(tmp, 'u') == NULL && strchr(tmp, 'g') == NULL &&
3416 strchr(tmp, 'p') == NULL &&
3417 strcmp(tmp, "none") != 0) {
3418 CERROR("enable option(%s) isn't supported\n", tmp);
3423 lustre_cfg_bufs_reset(&mgi->mgi_bufs, mti->mti_fsname);
3424 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, quota);
3425 lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
3429 /* truncate the comment to the parameter name */
3434 /* XXX we duplicated quota enable information in all server
3435 * config logs, it should be moved to a separate config
3436 * log once we cleanup the config log for global param. */
3437 /* modify all servers */
3438 rc = mgs_write_log_direct_all(env, mgs, fsdb, mti,
3439 *tmp == '\0' ? NULL : lcr,
3440 mti->mti_fsname, quota, 1);
3442 lustre_cfg_rec_free(lcr);
3443 return rc < 0 ? rc : 0;
3446 static int mgs_srpc_set_param_disk(const struct lu_env *env,
3447 struct mgs_device *mgs,
3449 struct mgs_target_info *mti,
3452 struct mgs_thread_info *mgi = mgs_env_info(env);
3453 struct llog_cfg_rec *lcr;
3454 struct llog_handle *llh = NULL;
3456 char *comment, *ptr;
3462 ptr = strchr(param, '=');
3463 LASSERT(ptr != NULL);
3466 OBD_ALLOC(comment, len + 1);
3467 if (comment == NULL)
3469 strncpy(comment, param, len);
3470 comment[len] = '\0';
3473 lustre_cfg_bufs_reset(&mgi->mgi_bufs, mti->mti_svname);
3474 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, param);
3475 lcr = lustre_cfg_rec_new(LCFG_SPTLRPC_CONF, &mgi->mgi_bufs);
3477 GOTO(out_comment, rc = -ENOMEM);
3479 /* construct log name */
3480 rc = name_create(&logname, mti->mti_fsname, "-sptlrpc");
3484 if (mgs_log_is_empty(env, mgs, logname)) {
3485 rc = record_start_log(env, mgs, &llh, logname);
3488 record_end_log(env, &llh);
3491 /* obsolete old one */
3492 rc = mgs_modify(env, mgs, fsdb, mti, logname, mti->mti_svname,
3496 /* write the new one */
3497 rc = mgs_write_log_direct(env, mgs, fsdb, logname, lcr,
3498 mti->mti_svname, comment);
3500 CERROR("%s: error writing log %s: rc = %d\n",
3501 mgs->mgs_obd->obd_name, logname, rc);
3503 name_destroy(&logname);
3505 lustre_cfg_rec_free(lcr);
3507 OBD_FREE(comment, len + 1);
3511 static int mgs_srpc_set_param_udesc_mem(struct fs_db *fsdb,
3516 /* disable the adjustable udesc parameter for now, i.e. use default
3517 * setting that client always ship udesc to MDT if possible. to enable
3518 * it simply remove the following line */
3521 ptr = strchr(param, '=');
3526 if (strcmp(param, PARAM_SRPC_UDESC))
3529 if (strcmp(ptr, "yes") == 0) {
3530 set_bit(FSDB_UDESC, &fsdb->fsdb_flags);
3531 CWARN("Enable user descriptor shipping from client to MDT\n");
3532 } else if (strcmp(ptr, "no") == 0) {
3533 clear_bit(FSDB_UDESC, &fsdb->fsdb_flags);
3534 CWARN("Disable user descriptor shipping from client to MDT\n");
3542 CERROR("Invalid param: %s\n", param);
3546 static int mgs_srpc_set_param_mem(struct fs_db *fsdb,
3550 struct sptlrpc_rule rule;
3551 struct sptlrpc_rule_set *rset;
3555 if (strncmp(param, PARAM_SRPC, sizeof(PARAM_SRPC) - 1) != 0) {
3556 CERROR("Invalid sptlrpc parameter: %s\n", param);
3560 if (strncmp(param, PARAM_SRPC_UDESC,
3561 sizeof(PARAM_SRPC_UDESC) - 1) == 0) {
3562 RETURN(mgs_srpc_set_param_udesc_mem(fsdb, param));
3565 if (strncmp(param, PARAM_SRPC_FLVR, sizeof(PARAM_SRPC_FLVR) - 1) != 0) {
3566 CERROR("Invalid sptlrpc flavor parameter: %s\n", param);
3570 param += sizeof(PARAM_SRPC_FLVR) - 1;
3572 rc = sptlrpc_parse_rule(param, &rule);
3576 /* mgs rules implies must be mgc->mgs */
3577 if (test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
3578 if ((rule.sr_from != LUSTRE_SP_MGC &&
3579 rule.sr_from != LUSTRE_SP_ANY) ||
3580 (rule.sr_to != LUSTRE_SP_MGS &&
3581 rule.sr_to != LUSTRE_SP_ANY))
3585 /* preapre room for this coming rule. svcname format should be:
3586 * - fsname: general rule
3587 * - fsname-tgtname: target-specific rule
3589 if (strchr(svname, '-')) {
3590 struct mgs_tgt_srpc_conf *tgtconf;
3593 for (tgtconf = fsdb->fsdb_srpc_tgt; tgtconf != NULL;
3594 tgtconf = tgtconf->mtsc_next) {
3595 if (!strcmp(tgtconf->mtsc_tgt, svname)) {
3604 OBD_ALLOC_PTR(tgtconf);
3605 if (tgtconf == NULL)
3608 name_len = strlen(svname);
3610 OBD_ALLOC(tgtconf->mtsc_tgt, name_len + 1);
3611 if (tgtconf->mtsc_tgt == NULL) {
3612 OBD_FREE_PTR(tgtconf);
3615 memcpy(tgtconf->mtsc_tgt, svname, name_len);
3617 tgtconf->mtsc_next = fsdb->fsdb_srpc_tgt;
3618 fsdb->fsdb_srpc_tgt = tgtconf;
3621 rset = &tgtconf->mtsc_rset;
3622 } else if (strcmp(svname, MGSSELF_NAME) == 0) {
3623 /* put _mgs related srpc rule directly in mgs ruleset */
3624 rset = &fsdb->fsdb_mgs->mgs_lut.lut_sptlrpc_rset;
3626 rset = &fsdb->fsdb_srpc_gen;
3629 rc = sptlrpc_rule_set_merge(rset, &rule);
3634 static int mgs_srpc_set_param(const struct lu_env *env,
3635 struct mgs_device *mgs,
3637 struct mgs_target_info *mti,
3647 /* keep a copy of original param, which could be destroied
3649 copy_size = strlen(param) + 1;
3650 OBD_ALLOC(copy, copy_size);
3653 memcpy(copy, param, copy_size);
3655 rc = mgs_srpc_set_param_mem(fsdb, mti->mti_svname, param);
3659 /* previous steps guaranteed the syntax is correct */
3660 rc = mgs_srpc_set_param_disk(env, mgs, fsdb, mti, copy);
3664 if (test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
3666 * for mgs rules, make them effective immediately.
3668 LASSERT(fsdb->fsdb_srpc_tgt == NULL);
3669 sptlrpc_target_update_exp_flavor(mgs->mgs_obd,
3670 &fsdb->fsdb_srpc_gen);
3674 OBD_FREE(copy, copy_size);
3678 struct mgs_srpc_read_data {
3679 struct fs_db *msrd_fsdb;
3683 static int mgs_srpc_read_handler(const struct lu_env *env,
3684 struct llog_handle *llh,
3685 struct llog_rec_hdr *rec, void *data)
3687 struct mgs_srpc_read_data *msrd = data;
3688 struct cfg_marker *marker;
3689 struct lustre_cfg *lcfg = REC_DATA(rec);
3690 char *svname, *param;
3694 if (rec->lrh_type != OBD_CFG_REC) {
3695 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
3699 cfg_len = REC_DATA_LEN(rec);
3701 rc = lustre_cfg_sanity_check(lcfg, cfg_len);
3703 CERROR("Insane cfg\n");
3707 if (lcfg->lcfg_command == LCFG_MARKER) {
3708 marker = lustre_cfg_buf(lcfg, 1);
3710 if (marker->cm_flags & CM_START &&
3711 marker->cm_flags & CM_SKIP)
3712 msrd->msrd_skip = 1;
3713 if (marker->cm_flags & CM_END)
3714 msrd->msrd_skip = 0;
3719 if (msrd->msrd_skip)
3722 if (lcfg->lcfg_command != LCFG_SPTLRPC_CONF) {
3723 CERROR("invalid command (%x)\n", lcfg->lcfg_command);
3727 svname = lustre_cfg_string(lcfg, 0);
3728 if (svname == NULL) {
3729 CERROR("svname is empty\n");
3733 param = lustre_cfg_string(lcfg, 1);
3734 if (param == NULL) {
3735 CERROR("param is empty\n");
3739 rc = mgs_srpc_set_param_mem(msrd->msrd_fsdb, svname, param);
3741 CERROR("read sptlrpc record error (%d): %s\n", rc, param);
3746 int mgs_get_fsdb_srpc_from_llog(const struct lu_env *env,
3747 struct mgs_device *mgs,
3750 struct llog_handle *llh = NULL;
3751 struct llog_ctxt *ctxt;
3753 struct mgs_srpc_read_data msrd;
3757 /* construct log name */
3758 rc = name_create(&logname, fsdb->fsdb_name, "-sptlrpc");
3762 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
3763 LASSERT(ctxt != NULL);
3765 if (mgs_log_is_empty(env, mgs, logname))
3768 rc = llog_open(env, ctxt, &llh, NULL, logname,
3776 rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL);
3778 GOTO(out_close, rc);
3780 if (llog_get_size(llh) <= 1)
3781 GOTO(out_close, rc = 0);
3783 msrd.msrd_fsdb = fsdb;
3786 rc = llog_process(env, llh, mgs_srpc_read_handler, (void *)&msrd,
3790 llog_close(env, llh);
3792 llog_ctxt_put(ctxt);
3793 name_destroy(&logname);
3796 CERROR("failed to read sptlrpc config database: %d\n", rc);
3800 static int mgs_write_log_param2(const struct lu_env *env,
3801 struct mgs_device *mgs,
3803 struct mgs_target_info *mti, char *ptr)
3805 struct lustre_cfg_bufs bufs;
3809 CDEBUG(D_MGS, "next param '%s'\n", ptr);
3811 /* PARAM_MGSNODE and PARAM_NETWORK are set only when formating
3812 * or during the inital mount. It can never change after that.
3814 if (!class_match_param(ptr, PARAM_MGSNODE, NULL) ||
3815 !class_match_param(ptr, PARAM_NETWORK, NULL)) {
3820 /* Processed in mgs_write_log_ost. Another value that can't
3821 * be changed by lctl set_param -P.
3823 if (!class_match_param(ptr, PARAM_FAILMODE, NULL)) {
3824 LCONSOLE_ERROR_MSG(0x169,
3825 "%s can only be changed with tunefs.lustre and --writeconf\n",
3831 /* FIXME !!! Support for sptlrpc is incomplete. Currently the change
3832 * doesn't transmit to the client. See LU-7183.
3834 if (!class_match_param(ptr, PARAM_SRPC, NULL)) {
3835 rc = mgs_srpc_set_param(env, mgs, fsdb, mti, ptr);
3839 /* Can't use class_match_param since ptr doesn't start with
3840 * PARAM_FAILNODE. So we look for PARAM_FAILNODE contained in ptr.
3842 if (strstr(ptr, PARAM_FAILNODE)) {
3843 /* Add a failover nidlist. We already processed failovers
3844 * params for new targets in mgs_write_log_target.
3848 /* can't use wildcards with failover.node */
3849 if (strchr(ptr, '*')) {
3854 param = strstr(ptr, PARAM_FAILNODE);
3855 if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
3856 sizeof(mti->mti_params)) {
3861 CDEBUG(D_MGS, "Adding failnode with param %s\n",
3863 rc = mgs_write_log_add_failnid(env, mgs, fsdb, mti);
3867 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, PARAMS_FILENAME, &bufs,
3868 mti->mti_svname, ptr);
3873 /* Permanent settings of all parameters by writing into the appropriate
3874 * configuration logs.
3875 * A parameter with null value ("<param>='\0'") means to erase it out of
3878 static int mgs_write_log_param(const struct lu_env *env,
3879 struct mgs_device *mgs, struct fs_db *fsdb,
3880 struct mgs_target_info *mti, char *ptr)
3882 struct mgs_thread_info *mgi = mgs_env_info(env);
3888 /* For various parameter settings, we have to figure out which logs
3889 care about them (e.g. both mdt and client for lov settings) */
3890 CDEBUG(D_MGS, "next param '%s'\n", ptr);
3892 /* The params are stored in MOUNT_DATA_FILE and modified via
3893 tunefs.lustre, or set using lctl conf_param */
3895 /* Processed in lustre_start_mgc */
3896 if (class_match_param(ptr, PARAM_MGSNODE, NULL) == 0)
3899 /* Processed in ost/mdt */
3900 if (class_match_param(ptr, PARAM_NETWORK, NULL) == 0)
3903 /* Processed in mgs_write_log_ost */
3904 if (class_match_param(ptr, PARAM_FAILMODE, NULL) == 0) {
3905 if (mti->mti_flags & LDD_F_PARAM) {
3906 LCONSOLE_ERROR_MSG(0x169, "%s can only be "
3907 "changed with tunefs.lustre"
3908 "and --writeconf\n", ptr);
3914 if (class_match_param(ptr, PARAM_SRPC, NULL) == 0) {
3915 rc = mgs_srpc_set_param(env, mgs, fsdb, mti, ptr);
3919 if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
3920 /* Add a failover nidlist */
3922 /* We already processed failovers params for new
3923 targets in mgs_write_log_target */
3924 if (mti->mti_flags & LDD_F_PARAM) {
3925 CDEBUG(D_MGS, "Adding failnode\n");
3926 rc = mgs_write_log_add_failnid(env, mgs, fsdb, mti);
3931 if (class_match_param(ptr, PARAM_SYS, &tmp) == 0) {
3932 rc = mgs_write_log_sys(env, mgs, fsdb, mti, ptr, tmp);
3936 if (class_match_param(ptr, PARAM_QUOTA, &tmp) == 0) {
3937 rc = mgs_write_log_quota(env, mgs, fsdb, mti, ptr, tmp);
3941 if (class_match_param(ptr, PARAM_OSC PARAM_ACTIVE, &tmp) == 0 ||
3942 class_match_param(ptr, PARAM_MDC PARAM_ACTIVE, &tmp) == 0) {
3943 /* active=0 means off, anything else means on */
3944 int flag = (*tmp == '0') ? CM_EXCLUDE : 0;
3945 bool deactive_osc = memcmp(ptr, PARAM_OSC PARAM_ACTIVE,
3946 strlen(PARAM_OSC PARAM_ACTIVE)) == 0;
3949 if (!deactive_osc) {
3952 rc = server_name2index(mti->mti_svname, &index, NULL);
3957 LCONSOLE_ERROR_MSG(0x144, "%s: MDC0 can not be"
3958 " (de)activated.\n",
3960 GOTO(end, rc = -EPERM);
3964 LCONSOLE_WARN("Permanently %sactivating %s\n",
3965 flag ? "de" : "re", mti->mti_svname);
3967 rc = name_create(&logname, mti->mti_fsname, "-client");
3970 rc = mgs_modify(env, mgs, fsdb, mti, logname,
3972 deactive_osc ? "add osc" : "add mdc", flag);
3973 name_destroy(&logname);
3978 /* Add to all MDT logs for DNE */
3979 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
3980 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
3982 rc = name_create_mdt(&logname, mti->mti_fsname, i);
3985 rc = mgs_modify(env, mgs, fsdb, mti, logname,
3987 deactive_osc ? "add osc" : "add osp",
3989 name_destroy(&logname);
3995 LCONSOLE_ERROR_MSG(0x145, "Couldn't find %s in"
3996 "log (%d). No permanent "
3997 "changes were made to the "
3999 mti->mti_svname, rc);
4000 if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags))
4001 LCONSOLE_ERROR_MSG(0x146, "This may be"
4006 "update the logs.\n");
4009 /* Fall through to osc/mdc proc for deactivating live
4010 OSC/OSP on running MDT / clients. */
4012 /* Below here, let obd's XXX_process_config methods handle it */
4014 /* All lov. in proc */
4015 if (class_match_param(ptr, PARAM_LOV, NULL) == 0) {
4018 CDEBUG(D_MGS, "lov param %s\n", ptr);
4019 if (!(mti->mti_flags & LDD_F_SV_TYPE_MDT)) {
4020 LCONSOLE_ERROR_MSG(0x147, "LOV params must be "
4021 "set on the MDT, not %s. "
4028 if (mgs_log_is_empty(env, mgs, mti->mti_svname))
4029 GOTO(end, rc = -ENODEV);
4031 rc = name_create_mdt_and_lov(&logname, &mdtlovname, fsdb,
4032 mti->mti_stripe_index);
4035 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, mti->mti_svname,
4036 &mgi->mgi_bufs, mdtlovname, ptr);
4037 name_destroy(&logname);
4038 name_destroy(&mdtlovname);
4043 rc = name_create(&logname, mti->mti_fsname, "-client");
4046 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname, &mgi->mgi_bufs,
4047 fsdb->fsdb_clilov, ptr);
4048 name_destroy(&logname);
4052 /* All osc., mdc., llite. params in proc */
4053 if ((class_match_param(ptr, PARAM_OSC, NULL) == 0) ||
4054 (class_match_param(ptr, PARAM_MDC, NULL) == 0) ||
4055 (class_match_param(ptr, PARAM_LLITE, NULL) == 0)) {
4058 if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
4059 LCONSOLE_ERROR_MSG(0x148, "Upgraded client logs for %s"
4060 " cannot be modified. Consider"
4061 " updating the configuration with"
4064 GOTO(end, rc = -EINVAL);
4066 if (memcmp(ptr, PARAM_LLITE, strlen(PARAM_LLITE)) == 0) {
4067 rc = name_create(&cname, mti->mti_fsname, "-client");
4068 /* Add the client type to match the obdname in
4069 class_config_llog_handler */
4070 } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
4071 rc = name_create(&cname, mti->mti_svname, "-mdc");
4072 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
4073 rc = name_create(&cname, mti->mti_svname, "-osc");
4075 GOTO(end, rc = -EINVAL);
4080 /* Forbid direct update of llite root squash parameters.
4081 * These parameters are indirectly set via the MDT settings.
4083 if ((class_match_param(ptr, PARAM_LLITE, &tmp) == 0) &&
4084 ((memcmp(tmp, "root_squash=", 12) == 0) ||
4085 (memcmp(tmp, "nosquash_nids=", 14) == 0))) {
4086 LCONSOLE_ERROR("%s: root squash parameters can only "
4087 "be updated through MDT component\n",
4089 name_destroy(&cname);
4090 GOTO(end, rc = -EINVAL);
4093 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
4096 rc = name_create(&logname, mti->mti_fsname, "-client");
4098 name_destroy(&cname);
4101 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname, &mgi->mgi_bufs,
4104 /* osc params affect the MDT as well */
4105 if (!rc && (mti->mti_flags & LDD_F_SV_TYPE_OST)) {
4108 for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
4109 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
4111 name_destroy(&cname);
4112 rc = name_create_mdt_osc(&cname, mti->mti_svname,
4114 name_destroy(&logname);
4117 rc = name_create_mdt(&logname,
4118 mti->mti_fsname, i);
4121 if (!mgs_log_is_empty(env, mgs, logname)) {
4122 rc = mgs_wlp_lcfg(env, mgs, fsdb,
4132 /* For mdc activate/deactivate, it affects OSP on MDT as well */
4133 if (class_match_param(ptr, PARAM_MDC PARAM_ACTIVE, &tmp) == 0 &&
4136 char *lodname = NULL;
4137 char *param_str = NULL;
4141 /* replace mdc with osp */
4142 memcpy(ptr, PARAM_OSP, strlen(PARAM_OSP));
4143 rc = server_name2index(mti->mti_svname, &index, NULL);
4145 memcpy(ptr, PARAM_MDC, strlen(PARAM_MDC));
4149 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
4150 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
4156 name_destroy(&logname);
4157 rc = name_create_mdt(&logname, mti->mti_fsname,
4162 if (mgs_log_is_empty(env, mgs, logname))
4165 snprintf(suffix, sizeof(suffix), "-osp-MDT%04x",
4167 name_destroy(&cname);
4168 rc = name_create(&cname, mti->mti_svname,
4173 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,
4174 &mgi->mgi_bufs, cname, ptr);
4178 /* Add configuration log for noitfying LOD
4179 * to active/deactive the OSP. */
4180 name_destroy(¶m_str);
4181 rc = name_create(¶m_str, cname,
4182 (*tmp == '0') ? ".active=0" :
4187 name_destroy(&lodname);
4188 rc = name_create(&lodname, logname, "-mdtlov");
4192 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,
4193 &mgi->mgi_bufs, lodname,
4198 memcpy(ptr, PARAM_MDC, strlen(PARAM_MDC));
4199 name_destroy(&lodname);
4200 name_destroy(¶m_str);
4203 name_destroy(&logname);
4204 name_destroy(&cname);
4208 /* All mdt. params in proc */
4209 if (class_match_param(ptr, PARAM_MDT, &tmp) == 0) {
4213 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
4214 if (strncmp(mti->mti_svname, mti->mti_fsname,
4215 MTI_NAME_MAXLEN) == 0)
4216 /* device is unspecified completely? */
4217 rc = LDD_F_SV_TYPE_MDT | LDD_F_SV_ALL;
4219 rc = server_name2index(mti->mti_svname, &idx, NULL);
4222 if ((rc & LDD_F_SV_TYPE_MDT) == 0)
4224 if (rc & LDD_F_SV_ALL) {
4225 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
4227 fsdb->fsdb_mdt_index_map))
4229 rc = name_create_mdt(&logname,
4230 mti->mti_fsname, i);
4233 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti,
4234 logname, &mgi->mgi_bufs,
4236 name_destroy(&logname);
4241 if ((memcmp(tmp, "root_squash=", 12) == 0) ||
4242 (memcmp(tmp, "nosquash_nids=", 14) == 0)) {
4243 LCONSOLE_ERROR("%s: root squash parameters "
4244 "cannot be applied to a single MDT\n",
4246 GOTO(end, rc = -EINVAL);
4248 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti,
4249 mti->mti_svname, &mgi->mgi_bufs,
4250 mti->mti_svname, ptr);
4255 /* root squash settings are also applied to llite
4256 * config log (see LU-1778) */
4258 ((memcmp(tmp, "root_squash=", 12) == 0) ||
4259 (memcmp(tmp, "nosquash_nids=", 14) == 0))) {
4263 rc = name_create(&cname, mti->mti_fsname, "-client");
4266 rc = name_create(&logname, mti->mti_fsname, "-client");
4268 name_destroy(&cname);
4271 rc = name_create(&ptr2, PARAM_LLITE, tmp);
4273 name_destroy(&cname);
4274 name_destroy(&logname);
4277 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,
4278 &mgi->mgi_bufs, cname, ptr2);
4279 name_destroy(&ptr2);
4280 name_destroy(&logname);
4281 name_destroy(&cname);
4286 /* All mdd., ost. and osd. params in proc */
4287 if ((class_match_param(ptr, PARAM_MDD, NULL) == 0) ||
4288 (class_match_param(ptr, PARAM_LOD, NULL) == 0) ||
4289 (class_match_param(ptr, PARAM_OST, NULL) == 0) ||
4290 (class_match_param(ptr, PARAM_OSD, NULL) == 0)) {
4291 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
4292 if (mgs_log_is_empty(env, mgs, mti->mti_svname))
4293 GOTO(end, rc = -ENODEV);
4295 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, mti->mti_svname,
4296 &mgi->mgi_bufs, mti->mti_svname, ptr);
4300 LCONSOLE_WARN("Ignoring unrecognized param '%s'\n", ptr);
4304 CERROR("err %d on param '%s'\n", rc, ptr);
4309 int mgs_write_log_target(const struct lu_env *env, struct mgs_device *mgs,
4310 struct mgs_target_info *mti, struct fs_db *fsdb)
4317 /* set/check the new target index */
4318 rc = mgs_set_index(env, mgs, mti);
4322 if (rc == EALREADY) {
4323 LCONSOLE_WARN("Found index %d for %s, updating log\n",
4324 mti->mti_stripe_index, mti->mti_svname);
4325 /* We would like to mark old log sections as invalid
4326 and add new log sections in the client and mdt logs.
4327 But if we add new sections, then live clients will
4328 get repeat setup instructions for already running
4329 osc's. So don't update the client/mdt logs. */
4330 mti->mti_flags &= ~LDD_F_UPDATE;
4334 OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_WRITE_TARGET_DELAY, cfs_fail_val > 0 ?
4337 mutex_lock(&fsdb->fsdb_mutex);
4339 if (mti->mti_flags & (LDD_F_VIRGIN | LDD_F_WRITECONF)) {
4340 /* Generate a log from scratch */
4341 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
4342 rc = mgs_write_log_mdt(env, mgs, fsdb, mti);
4343 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
4344 rc = mgs_write_log_ost(env, mgs, fsdb, mti);
4346 CERROR("Unknown target type %#x, can't create log for %s\n",
4347 mti->mti_flags, mti->mti_svname);
4350 CERROR("Can't write logs for %s (%d)\n",
4351 mti->mti_svname, rc);
4355 /* Just update the params from tunefs in mgs_write_log_params */
4356 CDEBUG(D_MGS, "Update params for %s\n", mti->mti_svname);
4357 mti->mti_flags |= LDD_F_PARAM;
4360 /* allocate temporary buffer, where class_get_next_param will
4361 make copy of a current parameter */
4362 OBD_ALLOC(buf, strlen(mti->mti_params) + 1);
4364 GOTO(out_up, rc = -ENOMEM);
4365 params = mti->mti_params;
4366 while (params != NULL) {
4367 rc = class_get_next_param(¶ms, buf);
4370 /* there is no next parameter, that is
4375 CDEBUG(D_MGS, "remaining string: '%s', param: '%s'\n",
4377 rc = mgs_write_log_param(env, mgs, fsdb, mti, buf);
4382 OBD_FREE(buf, strlen(mti->mti_params) + 1);
4385 mutex_unlock(&fsdb->fsdb_mutex);
4389 int mgs_erase_log(const struct lu_env *env, struct mgs_device *mgs, char *name)
4391 struct llog_ctxt *ctxt;
4394 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
4396 CERROR("%s: MGS config context doesn't exist\n",
4397 mgs->mgs_obd->obd_name);
4400 rc = llog_erase(env, ctxt, NULL, name);
4401 /* llog may not exist */
4404 llog_ctxt_put(ctxt);
4408 CERROR("%s: failed to clear log %s: %d\n",
4409 mgs->mgs_obd->obd_name, name, rc);
4414 /* erase all logs for the given fs */
4415 int mgs_erase_logs(const struct lu_env *env, struct mgs_device *mgs,
4418 struct list_head log_list;
4419 struct mgs_direntry *dirent, *n;
4420 char barrier_name[20] = {};
4423 int rc, len = strlen(fsname);
4426 mutex_lock(&mgs->mgs_mutex);
4428 /* Find all the logs in the CONFIGS directory */
4429 rc = class_dentry_readdir(env, mgs, &log_list);
4431 mutex_unlock(&mgs->mgs_mutex);
4435 if (list_empty(&log_list)) {
4436 mutex_unlock(&mgs->mgs_mutex);
4440 snprintf(barrier_name, sizeof(barrier_name) - 1, "%s-%s",
4441 fsname, BARRIER_FILENAME);
4442 /* Delete the barrier fsdb */
4443 mgs_remove_fsdb_by_name(mgs, barrier_name);
4444 /* Delete the fs db */
4445 mgs_remove_fsdb_by_name(mgs, fsname);
4446 mutex_unlock(&mgs->mgs_mutex);
4448 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4449 list_del_init(&dirent->mde_list);
4450 suffix = strrchr(dirent->mde_name, '-');
4451 if (suffix != NULL) {
4452 if ((len == suffix - dirent->mde_name) &&
4453 (strncmp(fsname, dirent->mde_name, len) == 0)) {
4454 CDEBUG(D_MGS, "Removing log %s\n",
4456 mgs_erase_log(env, mgs, dirent->mde_name);
4460 mgs_direntry_free(dirent);
4469 /* list all logs for the given fs */
4470 int mgs_list_logs(const struct lu_env *env, struct mgs_device *mgs,
4471 struct obd_ioctl_data *data)
4473 struct list_head log_list;
4474 struct mgs_direntry *dirent, *n;
4475 char *out, *suffix, prefix[] = "config_log: ";
4476 int prefix_len = strlen(prefix);
4477 int len, remains, start = 0, rc;
4481 /* Find all the logs in the CONFIGS directory */
4482 rc = class_dentry_readdir(env, mgs, &log_list);
4486 out = data->ioc_bulk;
4487 remains = data->ioc_inllen1;
4488 /* OBD_FAIL: fetch the config_log records from the specified one */
4489 if (OBD_FAIL_CHECK(OBD_FAIL_CATLIST))
4490 data->ioc_count = cfs_fail_val;
4492 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4493 list_del_init(&dirent->mde_list);
4494 suffix = strrchr(dirent->mde_name, '-');
4495 if (suffix != NULL) {
4496 len = prefix_len + dirent->mde_len + 1;
4497 if (remains - len < 0) {
4498 /* No enough space for this record */
4499 mgs_direntry_free(dirent);
4503 if (start < data->ioc_count) {
4504 mgs_direntry_free(dirent);
4507 len = scnprintf(out, remains, "%s%s\n", prefix,
4512 mgs_direntry_free(dirent);
4520 data->ioc_count = start;
4524 struct mgs_lcfg_fork_data {
4525 struct lustre_cfg_bufs mlfd_bufs;
4526 struct mgs_device *mlfd_mgs;
4527 struct llog_handle *mlfd_llh;
4528 const char *mlfd_oldname;
4529 const char *mlfd_newname;
4533 static bool contain_valid_fsname(char *buf, const char *fsname,
4534 int buflen, int namelen)
4536 if (buflen < namelen)
4539 if (memcmp(buf, fsname, namelen) != 0)
4542 if (buf[namelen] != '\0' && buf[namelen] != '-')
4548 static int mgs_lcfg_fork_handler(const struct lu_env *env,
4549 struct llog_handle *o_llh,
4550 struct llog_rec_hdr *o_rec, void *data)
4552 struct mgs_lcfg_fork_data *mlfd = data;
4553 struct lustre_cfg_bufs *n_bufs = &mlfd->mlfd_bufs;
4554 struct lustre_cfg *o_lcfg = (struct lustre_cfg *)(o_rec + 1);
4555 struct llog_cfg_rec *lcr;
4557 char *n_buf = mlfd->mlfd_data;
4559 int o_namelen = strlen(mlfd->mlfd_oldname);
4560 int n_namelen = strlen(mlfd->mlfd_newname);
4561 int diff = n_namelen - o_namelen;
4562 __u32 cmd = o_lcfg->lcfg_command;
4563 __u32 cnt = o_lcfg->lcfg_bufcount;
4569 o_buf = lustre_cfg_buf(o_lcfg, 0);
4570 o_buflen = o_lcfg->lcfg_buflens[0];
4571 if (contain_valid_fsname(o_buf, mlfd->mlfd_oldname, o_buflen,
4573 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4574 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4575 o_buflen - o_namelen);
4576 lustre_cfg_bufs_reset(n_bufs, n_buf);
4577 n_buf += cfs_size_round(o_buflen + diff);
4579 lustre_cfg_bufs_reset(n_bufs, o_buflen != 0 ? o_buf : NULL);
4584 struct cfg_marker *o_marker;
4585 struct cfg_marker *n_marker;
4589 CDEBUG(D_MGS, "Unknown cfg marker entry with %d "
4594 /* buf[1] is marker */
4595 o_buf = lustre_cfg_buf(o_lcfg, 1);
4596 o_buflen = o_lcfg->lcfg_buflens[1];
4597 o_marker = (struct cfg_marker *)o_buf;
4598 if (!contain_valid_fsname(o_marker->cm_tgtname,
4600 sizeof(o_marker->cm_tgtname),
4602 lustre_cfg_bufs_set(n_bufs, 1, o_marker,
4607 n_marker = (struct cfg_marker *)n_buf;
4608 *n_marker = *o_marker;
4609 memcpy(n_marker->cm_tgtname, mlfd->mlfd_newname, n_namelen);
4610 tgt_namelen = strlen(o_marker->cm_tgtname);
4611 if (tgt_namelen > o_namelen)
4612 memcpy(n_marker->cm_tgtname + n_namelen,
4613 o_marker->cm_tgtname + o_namelen,
4614 tgt_namelen - o_namelen);
4615 n_marker->cm_tgtname[tgt_namelen + diff] = '\0';
4616 lustre_cfg_bufs_set(n_bufs, 1, n_marker, sizeof(*n_marker));
4620 case LCFG_SET_PARAM: {
4621 for (i = 1; i < cnt; i++)
4622 /* buf[i] is the param value, reuse it directly */
4623 lustre_cfg_bufs_set(n_bufs, i,
4624 lustre_cfg_buf(o_lcfg, i),
4625 o_lcfg->lcfg_buflens[i]);
4631 case LCFG_POOL_DEL: {
4632 if (cnt < 3 || cnt > 4) {
4633 CDEBUG(D_MGS, "Unknown cfg pool (%x) entry with %d "
4634 "buffers\n", cmd, cnt);
4638 /* buf[1] is fsname */
4639 o_buf = lustre_cfg_buf(o_lcfg, 1);
4640 o_buflen = o_lcfg->lcfg_buflens[1];
4641 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4642 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4643 o_buflen - o_namelen);
4644 lustre_cfg_bufs_set(n_bufs, 1, n_buf, o_buflen + diff);
4645 n_buf += cfs_size_round(o_buflen + diff);
4647 /* buf[2] is the pool name, reuse it directly */
4648 lustre_cfg_bufs_set(n_bufs, 2, lustre_cfg_buf(o_lcfg, 2),
4649 o_lcfg->lcfg_buflens[2]);
4654 /* buf[3] is ostname */
4655 o_buf = lustre_cfg_buf(o_lcfg, 3);
4656 o_buflen = o_lcfg->lcfg_buflens[3];
4657 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4658 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4659 o_buflen - o_namelen);
4660 lustre_cfg_bufs_set(n_bufs, 3, n_buf, o_buflen + diff);
4665 o_buflen = o_lcfg->lcfg_buflens[1];
4666 if (o_buflen == sizeof(struct lov_desc) ||
4667 o_buflen == sizeof(struct lmv_desc)) {
4673 o_buf = lustre_cfg_buf(o_lcfg, 1);
4674 if (o_buflen == sizeof(struct lov_desc)) {
4675 struct lov_desc *o_desc =
4676 (struct lov_desc *)o_buf;
4677 struct lov_desc *n_desc =
4678 (struct lov_desc *)n_buf;
4681 o_uuid = o_desc->ld_uuid.uuid;
4682 n_uuid = n_desc->ld_uuid.uuid;
4683 uuid_len = sizeof(o_desc->ld_uuid.uuid);
4685 struct lmv_desc *o_desc =
4686 (struct lmv_desc *)o_buf;
4687 struct lmv_desc *n_desc =
4688 (struct lmv_desc *)n_buf;
4691 o_uuid = o_desc->ld_uuid.uuid;
4692 n_uuid = n_desc->ld_uuid.uuid;
4693 uuid_len = sizeof(o_desc->ld_uuid.uuid);
4696 if (unlikely(!contain_valid_fsname(o_uuid,
4697 mlfd->mlfd_oldname, uuid_len,
4699 lustre_cfg_bufs_set(n_bufs, 1, o_buf,
4704 memcpy(n_uuid, mlfd->mlfd_newname, n_namelen);
4705 uuid_len = strlen(o_uuid);
4706 if (uuid_len > o_namelen)
4707 memcpy(n_uuid + n_namelen,
4709 uuid_len - o_namelen);
4710 n_uuid[uuid_len + diff] = '\0';
4711 lustre_cfg_bufs_set(n_bufs, 1, n_buf, o_buflen);
4713 } /* else case fall through */
4714 } /* else case fall through */
4717 for (i = 1; i < cnt; i++) {
4718 o_buflen = o_lcfg->lcfg_buflens[i];
4722 o_buf = lustre_cfg_buf(o_lcfg, i);
4723 if (!contain_valid_fsname(o_buf, mlfd->mlfd_oldname,
4724 o_buflen, o_namelen)) {
4725 lustre_cfg_bufs_set(n_bufs, i, o_buf, o_buflen);
4729 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4730 if (o_buflen == o_namelen) {
4731 lustre_cfg_bufs_set(n_bufs, i, n_buf,
4733 n_buf += cfs_size_round(n_namelen);
4737 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4738 o_buflen - o_namelen);
4739 lustre_cfg_bufs_set(n_bufs, i, n_buf, o_buflen + diff);
4740 n_buf += cfs_size_round(o_buflen + diff);
4746 lcr = lustre_cfg_rec_new(cmd, n_bufs);
4750 lcr->lcr_cfg = *o_lcfg;
4751 rc = llog_write(env, mlfd->mlfd_llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
4752 lustre_cfg_rec_free(lcr);
4757 static int mgs_lcfg_fork_one(const struct lu_env *env, struct mgs_device *mgs,
4758 struct mgs_direntry *mde, const char *oldname,
4759 const char *newname)
4761 struct llog_handle *old_llh = NULL;
4762 struct llog_handle *new_llh = NULL;
4763 struct llog_ctxt *ctxt = NULL;
4764 struct mgs_lcfg_fork_data *mlfd = NULL;
4765 char *name_buf = NULL;
4767 int old_namelen = strlen(oldname);
4768 int new_namelen = strlen(newname);
4772 name_buflen = mde->mde_len + new_namelen - old_namelen;
4773 OBD_ALLOC(name_buf, name_buflen);
4777 memcpy(name_buf, newname, new_namelen);
4778 memcpy(name_buf + new_namelen, mde->mde_name + old_namelen,
4779 mde->mde_len - old_namelen);
4781 CDEBUG(D_MGS, "Fork the config-log from %s to %s\n",
4782 mde->mde_name, name_buf);
4784 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
4787 rc = llog_open_create(env, ctxt, &new_llh, NULL, name_buf);
4791 rc = llog_init_handle(env, new_llh, LLOG_F_IS_PLAIN, NULL);
4795 if (unlikely(mgs_log_is_empty(env, mgs, mde->mde_name)))
4798 rc = llog_open(env, ctxt, &old_llh, NULL, mde->mde_name,
4803 rc = llog_init_handle(env, old_llh, LLOG_F_IS_PLAIN, NULL);
4807 new_llh->lgh_hdr->llh_tgtuuid = old_llh->lgh_hdr->llh_tgtuuid;
4809 OBD_ALLOC(mlfd, LLOG_MIN_CHUNK_SIZE);
4811 GOTO(out, rc = -ENOMEM);
4813 mlfd->mlfd_mgs = mgs;
4814 mlfd->mlfd_llh = new_llh;
4815 mlfd->mlfd_oldname = oldname;
4816 mlfd->mlfd_newname = newname;
4818 rc = llog_process(env, old_llh, mgs_lcfg_fork_handler, mlfd, NULL);
4819 OBD_FREE(mlfd, LLOG_MIN_CHUNK_SIZE);
4825 llog_close(env, old_llh);
4827 llog_close(env, new_llh);
4829 OBD_FREE(name_buf, name_buflen);
4831 llog_ctxt_put(ctxt);
4836 int mgs_lcfg_fork(const struct lu_env *env, struct mgs_device *mgs,
4837 const char *oldname, const char *newname)
4839 struct list_head log_list;
4840 struct mgs_direntry *dirent, *n;
4841 int olen = strlen(oldname);
4842 int nlen = strlen(newname);
4847 if (unlikely(!oldname || oldname[0] == '\0' ||
4848 !newname || newname[0] == '\0'))
4851 if (strcmp(oldname, newname) == 0)
4854 /* lock it to prevent fork/erase/register in parallel. */
4855 mutex_lock(&mgs->mgs_mutex);
4857 rc = class_dentry_readdir(env, mgs, &log_list);
4859 mutex_unlock(&mgs->mgs_mutex);
4863 if (list_empty(&log_list)) {
4864 mutex_unlock(&mgs->mgs_mutex);
4868 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4871 ptr = strrchr(dirent->mde_name, '-');
4873 int tlen = ptr - dirent->mde_name;
4876 strncmp(newname, dirent->mde_name, tlen) == 0)
4877 GOTO(out, rc = -EEXIST);
4880 strncmp(oldname, dirent->mde_name, tlen) == 0)
4884 list_del_init(&dirent->mde_list);
4885 mgs_direntry_free(dirent);
4888 if (list_empty(&log_list)) {
4889 mutex_unlock(&mgs->mgs_mutex);
4893 list_for_each_entry(dirent, &log_list, mde_list) {
4894 rc = mgs_lcfg_fork_one(env, mgs, dirent, oldname, newname);
4902 mutex_unlock(&mgs->mgs_mutex);
4904 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4905 list_del_init(&dirent->mde_list);
4906 mgs_direntry_free(dirent);
4909 if (rc && count > 0)
4910 mgs_erase_logs(env, mgs, newname);
4915 int mgs_lcfg_erase(const struct lu_env *env, struct mgs_device *mgs,
4921 if (unlikely(!fsname || fsname[0] == '\0'))
4924 rc = mgs_erase_logs(env, mgs, fsname);
4929 static int mgs_xattr_del(const struct lu_env *env, struct dt_object *obj)
4931 struct dt_device *dev;
4932 struct thandle *th = NULL;
4937 dev = container_of0(obj->do_lu.lo_dev, struct dt_device, dd_lu_dev);
4938 th = dt_trans_create(env, dev);
4940 RETURN(PTR_ERR(th));
4942 rc = dt_declare_xattr_del(env, obj, XATTR_TARGET_RENAME, th);
4946 rc = dt_trans_start_local(env, dev, th);
4950 dt_write_lock(env, obj, 0);
4951 rc = dt_xattr_del(env, obj, XATTR_TARGET_RENAME, th);
4956 dt_write_unlock(env, obj);
4959 dt_trans_stop(env, dev, th);
4964 int mgs_lcfg_rename(const struct lu_env *env, struct mgs_device *mgs)
4966 struct list_head log_list;
4967 struct mgs_direntry *dirent, *n;
4969 struct lu_buf buf = {
4971 .lb_len = sizeof(fsname)
4977 rc = class_dentry_readdir(env, mgs, &log_list);
4981 if (list_empty(&log_list))
4984 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4985 struct dt_object *o = NULL;
4990 list_del_init(&dirent->mde_list);
4991 ptr = strrchr(dirent->mde_name, '-');
4995 len = ptr - dirent->mde_name;
4996 if (unlikely(len >= sizeof(oldname))) {
4997 CDEBUG(D_MGS, "Skip invalid configuration file %s\n",
5002 o = local_file_find(env, mgs->mgs_los, mgs->mgs_configs_dir,
5006 CDEBUG(D_MGS, "Fail to locate file %s: rc = %d\n",
5007 dirent->mde_name, rc);
5011 rc = dt_xattr_get(env, o, &buf, XATTR_TARGET_RENAME);
5017 "Fail to get EA for %s: rc = %d\n",
5018 dirent->mde_name, rc);
5022 if (unlikely(rc == len &&
5023 memcmp(fsname, dirent->mde_name, len) == 0)) {
5024 /* The new fsname is the same as the old one. */
5025 rc = mgs_xattr_del(env, o);
5029 memcpy(oldname, dirent->mde_name, len);
5030 oldname[len] = '\0';
5032 rc = mgs_lcfg_fork_one(env, mgs, dirent, oldname, fsname);
5033 if (rc && rc != -EEXIST) {
5034 CDEBUG(D_MGS, "Fail to fork %s: rc = %d\n",
5035 dirent->mde_name, rc);
5039 rc = mgs_erase_log(env, mgs, dirent->mde_name);
5041 CDEBUG(D_MGS, "Fail to erase old %s: rc = %d\n",
5042 dirent->mde_name, rc);
5043 /* keep it there if failed to remove it. */
5048 if (o && !IS_ERR(o))
5049 lu_object_put(env, &o->do_lu);
5051 mgs_direntry_free(dirent);
5056 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
5057 list_del_init(&dirent->mde_list);
5058 mgs_direntry_free(dirent);
5064 /* Setup _mgs fsdb and log
5066 int mgs__mgs_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs)
5068 struct fs_db *fsdb = NULL;
5072 rc = mgs_find_or_make_fsdb(env, mgs, MGSSELF_NAME, &fsdb);
5074 mgs_put_fsdb(mgs, fsdb);
5079 /* Setup params fsdb and log
5081 int mgs_params_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs)
5083 struct fs_db *fsdb = NULL;
5084 struct llog_handle *params_llh = NULL;
5088 rc = mgs_find_or_make_fsdb(env, mgs, PARAMS_FILENAME, &fsdb);
5090 mutex_lock(&fsdb->fsdb_mutex);
5091 rc = record_start_log(env, mgs, ¶ms_llh, PARAMS_FILENAME);
5093 rc = record_end_log(env, ¶ms_llh);
5094 mutex_unlock(&fsdb->fsdb_mutex);
5095 mgs_put_fsdb(mgs, fsdb);
5101 /* Cleanup params fsdb and log
5103 int mgs_params_fsdb_cleanup(const struct lu_env *env, struct mgs_device *mgs)
5107 rc = mgs_erase_logs(env, mgs, PARAMS_FILENAME);
5108 return rc == -ENOENT ? 0 : rc;
5112 * Fill in the mgs_target_info based on data devname and param provide.
5114 * @env thread context
5116 * @mti mgs target info. We want to set this based other paramters
5117 * passed to this function. Once setup we write it to the config
5119 * @devname optional OBD device name
5120 * @param string that contains both what tunable to set and the value to
5123 * RETURN 0 for success
5124 * negative error number on failure
5126 static int mgs_set_conf_param(const struct lu_env *env, struct mgs_device *mgs,
5127 struct mgs_target_info *mti, const char *devname,
5130 struct fs_db *fsdb = NULL;
5135 /* lustre, lustre-mdtlov, lustre-client, lustre-MDT0000 */
5139 /* We have two possible cases here:
5141 * 1) the device name embedded in the param:
5142 * lustre-OST0000.osc.max_dirty_mb=32
5144 * 2) the file system name is embedded in
5145 * the param: lustre.sys.at.min=0
5147 len = strcspn(param, ".=");
5148 if (!len || param[len] == '=')
5151 if (len >= sizeof(mti->mti_svname))
5154 snprintf(mti->mti_svname, sizeof(mti->mti_svname),
5155 "%.*s", (int)len, param);
5158 if (strlcpy(mti->mti_svname, devname, sizeof(mti->mti_svname)) >=
5159 sizeof(mti->mti_svname))
5163 if (!strlen(mti->mti_svname)) {
5164 LCONSOLE_ERROR_MSG(0x14d, "No target specified: %s\n", param);
5168 dev_type = mgs_parse_devname(mti->mti_svname, mti->mti_fsname,
5169 &mti->mti_stripe_index);
5171 /* For this case we have an invalid obd device name */
5173 CDEBUG(D_MGS, "%s don't contain an index\n", mti->mti_svname);
5174 strlcpy(mti->mti_fsname, mti->mti_svname, MTI_NAME_MAXLEN);
5177 /* Not an obd device, assume devname is the fsname.
5178 * User might of only provided fsname and not obd device
5181 CDEBUG(D_MGS, "%s is seen as a file system name\n", mti->mti_svname);
5182 strlcpy(mti->mti_fsname, mti->mti_svname, MTI_NAME_MAXLEN);
5187 GOTO(out, rc = dev_type);
5189 /* param related to llite isn't allowed to set by OST or MDT */
5190 if (dev_type & LDD_F_SV_TYPE_OST ||
5191 dev_type & LDD_F_SV_TYPE_MDT) {
5192 /* param related to llite isn't allowed to set by OST
5195 if (!strncmp(param, PARAM_LLITE,
5196 sizeof(PARAM_LLITE) - 1))
5197 GOTO(out, rc = -EINVAL);
5199 /* Strip -osc or -mdc suffix from svname */
5200 if (server_make_name(dev_type, mti->mti_stripe_index,
5201 mti->mti_fsname, mti->mti_svname,
5202 sizeof(mti->mti_svname)))
5203 GOTO(out, rc = -EINVAL);
5208 if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
5209 sizeof(mti->mti_params))
5210 GOTO(out, rc = -E2BIG);
5212 CDEBUG(D_MGS, "set_conf_param fs='%s' device='%s' param='%s'\n",
5213 mti->mti_fsname, mti->mti_svname, mti->mti_params);
5215 rc = mgs_find_or_make_fsdb(env, mgs, mti->mti_fsname, &fsdb);
5219 if (!test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags) &&
5220 test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
5221 CERROR("No filesystem targets for %s. cfg_device from lctl "
5222 "is '%s'\n", mti->mti_fsname, mti->mti_svname);
5223 mgs_unlink_fsdb(mgs, fsdb);
5224 GOTO(out, rc = -EINVAL);
5228 * Revoke lock so everyone updates. Should be alright if
5229 * someone was already reading while we were updating the logs,
5230 * so we don't really need to hold the lock while we're
5233 mti->mti_flags = dev_type | LDD_F_PARAM;
5234 mutex_lock(&fsdb->fsdb_mutex);
5235 rc = mgs_write_log_param(env, mgs, fsdb, mti, mti->mti_params);
5236 mutex_unlock(&fsdb->fsdb_mutex);
5237 mgs_revoke_lock(mgs, fsdb, CONFIG_T_CONFIG);
5241 mgs_put_fsdb(mgs, fsdb);
5246 static int mgs_set_param2(const struct lu_env *env, struct mgs_device *mgs,
5247 struct mgs_target_info *mti, const char *param)
5249 struct fs_db *fsdb = NULL;
5254 if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
5255 sizeof(mti->mti_params))
5256 GOTO(out, rc = -E2BIG);
5258 /* obdname2fsname reports devname as an obd device */
5259 len = strcspn(param, ".=");
5260 if (len && param[len] != '=') {
5264 ptr = strchr(param, '.');
5266 len = strlen(param);
5269 if (len >= sizeof(mti->mti_svname))
5270 GOTO(out, rc = -E2BIG);
5272 snprintf(mti->mti_svname, sizeof(mti->mti_svname), "%.*s",
5275 obdname2fsname(mti->mti_svname, mti->mti_fsname,
5276 sizeof(mti->mti_fsname));
5278 snprintf(mti->mti_svname, sizeof(mti->mti_svname), "general");
5281 CDEBUG(D_MGS, "set_param2 fs='%s' device='%s' param='%s'\n",
5282 mti->mti_fsname, mti->mti_svname, mti->mti_params);
5284 /* The return value should be the device type i.e LDD_F_SV_TYPE_XXX.
5285 * A returned error tells us we don't have a target obd device.
5287 dev_type = server_name2index(mti->mti_svname, &mti->mti_stripe_index,
5292 /* the return value should be the device type i.e LDD_F_SV_TYPE_XXX.
5293 * Strip -osc or -mdc suffix from svname
5295 if ((dev_type & LDD_F_SV_TYPE_OST || dev_type & LDD_F_SV_TYPE_MDT) &&
5296 server_make_name(dev_type, mti->mti_stripe_index,
5297 mti->mti_fsname, mti->mti_svname,
5298 sizeof(mti->mti_svname)))
5299 GOTO(out, rc = -EINVAL);
5301 rc = mgs_find_or_make_fsdb(env, mgs, PARAMS_FILENAME, &fsdb);
5305 * Revoke lock so everyone updates. Should be alright if
5306 * someone was already reading while we were updating the logs,
5307 * so we don't really need to hold the lock while we're
5310 mti->mti_flags = dev_type | LDD_F_PARAM2;
5311 mutex_lock(&fsdb->fsdb_mutex);
5312 rc = mgs_write_log_param2(env, mgs, fsdb, mti, mti->mti_params);
5313 mutex_unlock(&fsdb->fsdb_mutex);
5314 mgs_revoke_lock(mgs, fsdb, CONFIG_T_PARAMS);
5315 mgs_put_fsdb(mgs, fsdb);
5320 /* Set a permanent (config log) param for a target or fs
5322 * @lcfg buf0 may contain the device (testfs-MDT0000) name
5323 * buf1 contains the single parameter
5325 int mgs_set_param(const struct lu_env *env, struct mgs_device *mgs,
5326 struct lustre_cfg *lcfg)
5328 const char *param = lustre_cfg_string(lcfg, 1);
5329 struct mgs_target_info *mti;
5332 /* Create a fake mti to hold everything */
5337 print_lustre_cfg(lcfg);
5339 if (lcfg->lcfg_command == LCFG_PARAM) {
5340 /* For the case of lctl conf_param devname can be
5341 * lustre, lustre-mdtlov, lustre-client, lustre-MDT0000
5343 const char *devname = lustre_cfg_string(lcfg, 0);
5345 rc = mgs_set_conf_param(env, mgs, mti, devname, param);
5347 /* In the case of lctl set_param -P lcfg[0] will always
5348 * be 'general'. At least for now.
5350 rc = mgs_set_param2(env, mgs, mti, param);
5358 static int mgs_write_log_pool(const struct lu_env *env,
5359 struct mgs_device *mgs, char *logname,
5360 struct fs_db *fsdb, char *tgtname,
5361 enum lcfg_command_type cmd,
5362 char *fsname, char *poolname,
5363 char *ostname, char *comment)
5365 struct llog_handle *llh = NULL;
5368 rc = record_start_log(env, mgs, &llh, logname);
5371 rc = record_marker(env, llh, fsdb, CM_START, tgtname, comment);
5374 rc = record_base(env, llh, tgtname, 0, cmd,
5375 fsname, poolname, ostname, NULL);
5378 rc = record_marker(env, llh, fsdb, CM_END, tgtname, comment);
5380 record_end_log(env, &llh);
5384 int mgs_nodemap_cmd(const struct lu_env *env, struct mgs_device *mgs,
5385 enum lcfg_command_type cmd, const char *nodemap_name,
5396 case LCFG_NODEMAP_ADD:
5397 rc = nodemap_add(nodemap_name);
5399 case LCFG_NODEMAP_DEL:
5400 rc = nodemap_del(nodemap_name);
5402 case LCFG_NODEMAP_ADD_RANGE:
5403 rc = nodemap_parse_range(param, nid);
5406 rc = nodemap_add_range(nodemap_name, nid);
5408 case LCFG_NODEMAP_DEL_RANGE:
5409 rc = nodemap_parse_range(param, nid);
5412 rc = nodemap_del_range(nodemap_name, nid);
5414 case LCFG_NODEMAP_ADMIN:
5415 bool_switch = simple_strtoul(param, NULL, 10);
5416 rc = nodemap_set_allow_root(nodemap_name, bool_switch);
5418 case LCFG_NODEMAP_DENY_UNKNOWN:
5419 bool_switch = simple_strtoul(param, NULL, 10);
5420 rc = nodemap_set_deny_unknown(nodemap_name, bool_switch);
5422 case LCFG_NODEMAP_AUDIT_MODE:
5423 rc = kstrtoul(param, 10, (unsigned long *)&bool_switch);
5425 rc = nodemap_set_audit_mode(nodemap_name, bool_switch);
5427 case LCFG_NODEMAP_MAP_MODE:
5428 if (strcmp("both", param) == 0)
5429 rc = nodemap_set_mapping_mode(nodemap_name,
5431 else if (strcmp("uid_only", param) == 0)
5432 rc = nodemap_set_mapping_mode(nodemap_name,
5433 NODEMAP_MAP_UID_ONLY);
5434 else if (strcmp("gid_only", param) == 0)
5435 rc = nodemap_set_mapping_mode(nodemap_name,
5436 NODEMAP_MAP_GID_ONLY);
5440 case LCFG_NODEMAP_TRUSTED:
5441 bool_switch = simple_strtoul(param, NULL, 10);
5442 rc = nodemap_set_trust_client_ids(nodemap_name, bool_switch);
5444 case LCFG_NODEMAP_SQUASH_UID:
5445 int_id = simple_strtoul(param, NULL, 10);
5446 rc = nodemap_set_squash_uid(nodemap_name, int_id);
5448 case LCFG_NODEMAP_SQUASH_GID:
5449 int_id = simple_strtoul(param, NULL, 10);
5450 rc = nodemap_set_squash_gid(nodemap_name, int_id);
5452 case LCFG_NODEMAP_ADD_UIDMAP:
5453 case LCFG_NODEMAP_ADD_GIDMAP:
5454 rc = nodemap_parse_idmap(param, idmap);
5457 if (cmd == LCFG_NODEMAP_ADD_UIDMAP)
5458 rc = nodemap_add_idmap(nodemap_name, NODEMAP_UID,
5461 rc = nodemap_add_idmap(nodemap_name, NODEMAP_GID,
5464 case LCFG_NODEMAP_DEL_UIDMAP:
5465 case LCFG_NODEMAP_DEL_GIDMAP:
5466 rc = nodemap_parse_idmap(param, idmap);
5469 if (cmd == LCFG_NODEMAP_DEL_UIDMAP)
5470 rc = nodemap_del_idmap(nodemap_name, NODEMAP_UID,
5473 rc = nodemap_del_idmap(nodemap_name, NODEMAP_GID,
5476 case LCFG_NODEMAP_SET_FILESET:
5477 rc = nodemap_set_fileset(nodemap_name, param);
5479 case LCFG_NODEMAP_SET_SEPOL:
5480 rc = nodemap_set_sepol(nodemap_name, param);
5489 int mgs_pool_cmd(const struct lu_env *env, struct mgs_device *mgs,
5490 enum lcfg_command_type cmd, char *fsname,
5491 char *poolname, char *ostname)
5496 char *label = NULL, *canceled_label = NULL;
5498 struct mgs_target_info *mti = NULL;
5499 bool checked = false;
5500 bool locked = false;
5505 rc = mgs_find_or_make_fsdb(env, mgs, fsname, &fsdb);
5507 CERROR("Can't get db for %s\n", fsname);
5510 if (test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
5511 CERROR("%s is not defined\n", fsname);
5513 GOTO(out_fsdb, rc = -EINVAL);
5516 label_sz = 10 + strlen(fsname) + strlen(poolname);
5518 /* check if ostname match fsname */
5519 if (ostname != NULL) {
5522 ptr = strrchr(ostname, '-');
5523 if ((ptr == NULL) ||
5524 (strncmp(fsname, ostname, ptr-ostname) != 0))
5526 label_sz += strlen(ostname);
5529 OBD_ALLOC(label, label_sz);
5531 GOTO(out_fsdb, rc = -ENOMEM);
5536 "new %s.%s", fsname, poolname);
5540 "add %s.%s.%s", fsname, poolname, ostname);
5543 OBD_ALLOC(canceled_label, label_sz);
5544 if (canceled_label == NULL)
5545 GOTO(out_label, rc = -ENOMEM);
5547 "rem %s.%s.%s", fsname, poolname, ostname);
5548 sprintf(canceled_label,
5549 "add %s.%s.%s", fsname, poolname, ostname);
5552 OBD_ALLOC(canceled_label, label_sz);
5553 if (canceled_label == NULL)
5554 GOTO(out_label, rc = -ENOMEM);
5556 "del %s.%s", fsname, poolname);
5557 sprintf(canceled_label,
5558 "new %s.%s", fsname, poolname);
5566 GOTO(out_cancel, rc = -ENOMEM);
5567 strncpy(mti->mti_svname, "lov pool", sizeof(mti->mti_svname));
5569 mutex_lock(&fsdb->fsdb_mutex);
5571 /* write pool def to all MDT logs */
5572 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
5573 if (test_bit(i, fsdb->fsdb_mdt_index_map)) {
5574 rc = name_create_mdt_and_lov(&logname, &lovname,
5579 if (!checked && (canceled_label == NULL)) {
5580 rc = mgs_check_marker(env, mgs, fsdb, mti,
5581 logname, lovname, label);
5583 name_destroy(&logname);
5584 name_destroy(&lovname);
5586 rc = (rc == LLOG_PROC_BREAK ?
5591 if (canceled_label != NULL)
5592 rc = mgs_modify(env, mgs, fsdb, mti, logname,
5593 lovname, canceled_label,
5597 rc = mgs_write_log_pool(env, mgs, logname,
5601 name_destroy(&logname);
5602 name_destroy(&lovname);
5608 rc = name_create(&logname, fsname, "-client");
5612 if (!checked && (canceled_label == NULL)) {
5613 rc = mgs_check_marker(env, mgs, fsdb, mti, logname,
5614 fsdb->fsdb_clilov, label);
5616 name_destroy(&logname);
5617 GOTO(out_mti, rc = (rc == LLOG_PROC_BREAK ?
5621 if (canceled_label != NULL) {
5622 rc = mgs_modify(env, mgs, fsdb, mti, logname,
5623 fsdb->fsdb_clilov, canceled_label, CM_SKIP);
5625 name_destroy(&logname);
5630 rc = mgs_write_log_pool(env, mgs, logname, fsdb, fsdb->fsdb_clilov,
5631 cmd, fsname, poolname, ostname, label);
5632 mutex_unlock(&fsdb->fsdb_mutex);
5634 name_destroy(&logname);
5635 /* request for update */
5636 mgs_revoke_lock(mgs, fsdb, CONFIG_T_CONFIG);
5642 mutex_unlock(&fsdb->fsdb_mutex);
5646 if (canceled_label != NULL)
5647 OBD_FREE(canceled_label, label_sz);
5649 OBD_FREE(label, label_sz);
5652 mgs_unlink_fsdb(mgs, fsdb);
5653 mgs_put_fsdb(mgs, fsdb);