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 backup files */
110 if (lu_name_is_backup_file(key, key_sz, NULL)) {
111 CDEBUG(D_MGS, "Skipping backup file %.*s\n",
116 de = mgs_direntry_alloc(key_sz + 1);
122 memcpy(de->mde_name, key, key_sz);
123 de->mde_name[key_sz] = 0;
125 list_add(&de->mde_list, log_list);
128 rc = iops->next(env, it);
138 struct mgs_direntry *n;
140 CERROR("%s: key failed when listing %s: rc = %d\n",
141 mgs->mgs_obd->obd_name, MOUNT_CONFIGS_DIR, rc);
143 list_for_each_entry_safe(de, n, log_list, mde_list) {
144 list_del_init(&de->mde_list);
145 mgs_direntry_free(de);
152 /******************** DB functions *********************/
154 static inline int name_create(char **newname, char *prefix, char *suffix)
157 OBD_ALLOC(*newname, strlen(prefix) + strlen(suffix) + 1);
160 sprintf(*newname, "%s%s", prefix, suffix);
164 static inline void name_destroy(char **name)
167 OBD_FREE(*name, strlen(*name) + 1);
171 struct mgs_fsdb_handler_data
177 /* from the (client) config log, figure out:
178 1. which ost's/mdt's are configured (by index)
179 2. what the last config step is
180 3. COMPAT_18 osc name
182 /* It might be better to have a separate db file, instead of parsing the info
183 out of the client log. This is slow and potentially error-prone. */
184 static int mgs_fsdb_handler(const struct lu_env *env, struct llog_handle *llh,
185 struct llog_rec_hdr *rec, void *data)
187 struct mgs_fsdb_handler_data *d = data;
188 struct fs_db *fsdb = d->fsdb;
189 int cfg_len = rec->lrh_len;
190 char *cfg_buf = (char*) (rec + 1);
191 struct lustre_cfg *lcfg;
196 if (rec->lrh_type != OBD_CFG_REC) {
197 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
201 rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
203 CERROR("Insane cfg\n");
207 lcfg = (struct lustre_cfg *)cfg_buf;
209 CDEBUG(D_INFO, "cmd %x %s %s\n", lcfg->lcfg_command,
210 lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
212 /* Figure out ost indicies */
213 /* lov_modify_tgts add 0:lov1 1:ost1_UUID 2(index):0 3(gen):1 */
214 if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD ||
215 lcfg->lcfg_command == LCFG_LOV_DEL_OBD) {
216 rc = kstrtouint(lustre_cfg_string(lcfg, 2), 10, &index);
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)
1516 if (exp_connect_flags(exp) & OBD_CONNECT_MDS_MDS)
1521 CERROR("%s: node %s still connected during replace_nids "
1522 "connect_flags:%llx\n",
1524 libcfs_nid2str(exp->exp_nid_stats->nid),
1525 exp_connect_flags(exp));
1528 spin_unlock(&mgs_obd->obd_dev_lock);
1530 /* osd, MGS and MGC + self_export
1531 (wc -l /proc/fs/lustre/devices <= 2) && (non self exports == 0) */
1532 return (num_devices <= 3) && (num_exports == 0);
1535 static int name_create_mdt(char **logname, char *fsname, int mdt_idx)
1539 if (mdt_idx > INDEX_MAP_MAX_VALUE)
1542 snprintf(postfix, sizeof(postfix), "-MDT%04x", mdt_idx);
1543 return name_create(logname, fsname, postfix);
1547 * Replace nids for \a device to \a nids values
1549 * \param obd MGS obd device
1550 * \param devname nids need to be replaced for this device
1551 * (ex. lustre-OST0000)
1552 * \param nids nids list (ex. nid1,nid2,nid3)
1556 int mgs_replace_nids(const struct lu_env *env,
1557 struct mgs_device *mgs,
1558 char *devname, char *nids)
1560 /* Assume fsname is part of device name */
1561 char fsname[MTI_NAME_MAXLEN];
1565 struct fs_db *fsdb = NULL;
1568 struct obd_device *mgs_obd = mgs->mgs_obd;
1571 /* We can only change NIDs if no other nodes are connected */
1572 spin_lock(&mgs_obd->obd_dev_lock);
1573 conn_state = mgs_obd->obd_no_conn;
1574 mgs_obd->obd_no_conn = 1;
1575 spin_unlock(&mgs_obd->obd_dev_lock);
1577 /* We can not change nids if not only MGS is started */
1578 if (!only_mgs_is_running(mgs_obd)) {
1579 CERROR("Only MGS is allowed to be started\n");
1580 GOTO(out, rc = -EINPROGRESS);
1583 /* Get fsname and index */
1584 rc = mgs_parse_devname(devname, fsname, &index);
1588 rc = mgs_find_or_make_fsdb(env, mgs, fsname, &fsdb);
1590 CERROR("%s: can't find fsdb: rc = %d\n", fsname, rc);
1594 /* Process client llogs */
1595 rc = name_create(&logname, fsname, "-client");
1598 rc = mgs_replace_nids_log(env, mgs_obd, logname, devname, nids);
1599 name_destroy(&logname);
1601 CERROR("%s: error while replacing NIDs for %s: rc = %d\n",
1602 fsname, devname, rc);
1606 /* Process MDT llogs */
1607 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
1608 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
1610 rc = name_create_mdt(&logname, fsname, i);
1613 rc = mgs_replace_nids_log(env, mgs_obd, logname, devname, nids);
1614 name_destroy(&logname);
1620 spin_lock(&mgs_obd->obd_dev_lock);
1621 mgs_obd->obd_no_conn = conn_state;
1622 spin_unlock(&mgs_obd->obd_dev_lock);
1625 mgs_put_fsdb(mgs, fsdb);
1631 * This is called for every record in llog. Some of records are
1632 * skipped, others are copied to new log as is.
1633 * Records to be skipped are
1634 * marker records marked SKIP
1635 * records enclosed between SKIP markers
1637 * \param[in] llh log to be processed
1638 * \param[in] rec current record
1639 * \param[in] data mgs_replace_data structure
1643 static int mgs_clear_config_handler(const struct lu_env *env,
1644 struct llog_handle *llh,
1645 struct llog_rec_hdr *rec, void *data)
1647 struct mgs_replace_data *mrd;
1648 struct lustre_cfg *lcfg = REC_DATA(rec);
1649 int cfg_len = REC_DATA_LEN(rec);
1654 mrd = (struct mgs_replace_data *)data;
1656 if (rec->lrh_type != OBD_CFG_REC) {
1657 CDEBUG(D_MGS, "Config llog Name=%s, Record Index=%u, "
1658 "Unhandled Record Type=%#x\n", llh->lgh_name,
1659 rec->lrh_index, rec->lrh_type);
1663 rc = lustre_cfg_sanity_check(lcfg, cfg_len);
1665 CDEBUG(D_MGS, "Config llog Name=%s, Invalid config file.",
1670 if (lcfg->lcfg_command == LCFG_MARKER) {
1671 struct cfg_marker *marker;
1673 marker = lustre_cfg_buf(lcfg, 1);
1674 if (marker->cm_flags & CM_SKIP) {
1675 if (marker->cm_flags & CM_START)
1676 mrd->state = REPLACE_SKIP;
1677 if (marker->cm_flags & CM_END)
1678 mrd->state = REPLACE_COPY;
1679 /* SKIP section started or finished */
1680 CDEBUG(D_MGS, "Skip idx=%d, rc=%d, len=%d, "
1681 "cmd %x %s %s\n", rec->lrh_index, rc,
1682 rec->lrh_len, lcfg->lcfg_command,
1683 lustre_cfg_string(lcfg, 0),
1684 lustre_cfg_string(lcfg, 1));
1688 if (mrd->state == REPLACE_SKIP) {
1689 /* record enclosed between SKIP markers, skip it */
1690 CDEBUG(D_MGS, "Skip idx=%d, rc=%d, len=%d, "
1691 "cmd %x %s %s\n", rec->lrh_index, rc,
1692 rec->lrh_len, lcfg->lcfg_command,
1693 lustre_cfg_string(lcfg, 0),
1694 lustre_cfg_string(lcfg, 1));
1699 /* Record is placed in temporary llog as is */
1700 rc = llog_write(env, mrd->temp_llh, rec, LLOG_NEXT_IDX);
1702 CDEBUG(D_MGS, "Copied idx=%d, rc=%d, len=%d, cmd %x %s %s\n",
1703 rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
1704 lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
1709 * Directory CONFIGS/ may contain files which are not config logs to
1710 * be cleared. Skip any llogs with a non-alphanumeric character after
1711 * the last '-'. For example, fsname-MDT0000.sav, fsname-MDT0000.bak,
1712 * fsname-MDT0000.orig, fsname-MDT0000~, fsname-MDT0000.20150516, etc.
1714 static bool config_to_clear(const char *logname)
1719 str = strrchr(logname, '-');
1724 while (isalnum(str[++i]));
1725 return str[i] == '\0';
1729 * Clear config logs for \a name
1732 * \param mgs MGS device
1733 * \param name name of device or of filesystem
1734 * (ex. lustre-OST0000 or lustre) in later case all logs
1739 int mgs_clear_configs(const struct lu_env *env,
1740 struct mgs_device *mgs, const char *name)
1742 struct list_head dentry_list;
1743 struct mgs_direntry *dirent, *n;
1746 struct obd_device *mgs_obd = mgs->mgs_obd;
1751 /* Prevent clients and servers from connecting to mgs */
1752 spin_lock(&mgs_obd->obd_dev_lock);
1753 conn_state = mgs_obd->obd_no_conn;
1754 mgs_obd->obd_no_conn = 1;
1755 spin_unlock(&mgs_obd->obd_dev_lock);
1758 * config logs cannot be cleaned if anything other than
1761 if (!only_mgs_is_running(mgs_obd)) {
1762 CERROR("Only MGS is allowed to be started\n");
1763 GOTO(out, rc = -EBUSY);
1766 /* Find all the logs in the CONFIGS directory */
1767 rc = class_dentry_readdir(env, mgs, &dentry_list);
1769 CERROR("%s: cannot read config directory '%s': rc = %d\n",
1770 mgs_obd->obd_name, MOUNT_CONFIGS_DIR, rc);
1774 if (list_empty(&dentry_list)) {
1775 CERROR("%s: list empty reading config dir '%s': rc = %d\n",
1776 mgs_obd->obd_name, MOUNT_CONFIGS_DIR, -ENOENT);
1777 GOTO(out, rc = -ENOENT);
1780 OBD_ALLOC(namedash, strlen(name) + 2);
1781 if (namedash == NULL)
1782 GOTO(out, rc = -ENOMEM);
1783 snprintf(namedash, strlen(name) + 2, "%s-", name);
1785 list_for_each_entry(dirent, &dentry_list, mde_list) {
1786 if (strcmp(name, dirent->mde_name) &&
1787 strncmp(namedash, dirent->mde_name, strlen(namedash)))
1789 if (!config_to_clear(dirent->mde_name))
1791 CDEBUG(D_MGS, "%s: Clear config log %s\n",
1792 mgs_obd->obd_name, dirent->mde_name);
1793 rc = mgs_replace_log(env, mgs_obd, dirent->mde_name, NULL,
1794 mgs_clear_config_handler, NULL);
1799 list_for_each_entry_safe(dirent, n, &dentry_list, mde_list) {
1800 list_del_init(&dirent->mde_list);
1801 mgs_direntry_free(dirent);
1803 OBD_FREE(namedash, strlen(name) + 2);
1805 spin_lock(&mgs_obd->obd_dev_lock);
1806 mgs_obd->obd_no_conn = conn_state;
1807 spin_unlock(&mgs_obd->obd_dev_lock);
1812 static int record_lov_setup(const struct lu_env *env, struct llog_handle *llh,
1813 char *devname, struct lov_desc *desc)
1815 struct mgs_thread_info *mgi = mgs_env_info(env);
1816 struct llog_cfg_rec *lcr;
1819 lustre_cfg_bufs_reset(&mgi->mgi_bufs, devname);
1820 lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, desc, sizeof(*desc));
1821 lcr = lustre_cfg_rec_new(LCFG_SETUP, &mgi->mgi_bufs);
1825 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1826 lustre_cfg_rec_free(lcr);
1830 static int record_lmv_setup(const struct lu_env *env, struct llog_handle *llh,
1831 char *devname, struct lmv_desc *desc)
1833 struct mgs_thread_info *mgi = mgs_env_info(env);
1834 struct llog_cfg_rec *lcr;
1837 lustre_cfg_bufs_reset(&mgi->mgi_bufs, devname);
1838 lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, desc, sizeof(*desc));
1839 lcr = lustre_cfg_rec_new(LCFG_SETUP, &mgi->mgi_bufs);
1843 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1844 lustre_cfg_rec_free(lcr);
1848 static inline int record_mdc_add(const struct lu_env *env,
1849 struct llog_handle *llh,
1850 char *logname, char *mdcuuid,
1851 char *mdtuuid, char *index,
1854 return record_base(env,llh,logname,0,LCFG_ADD_MDC,
1855 mdtuuid,index,gen,mdcuuid);
1858 static inline int record_lov_add(const struct lu_env *env,
1859 struct llog_handle *llh,
1860 char *lov_name, char *ost_uuid,
1861 char *index, char *gen)
1863 return record_base(env, llh, lov_name, 0, LCFG_LOV_ADD_OBD,
1864 ost_uuid, index, gen, NULL);
1867 static inline int record_mount_opt(const struct lu_env *env,
1868 struct llog_handle *llh,
1869 char *profile, char *lov_name,
1872 return record_base(env, llh, NULL, 0, LCFG_MOUNTOPT,
1873 profile, lov_name, mdc_name, NULL);
1876 static int record_marker(const struct lu_env *env,
1877 struct llog_handle *llh,
1878 struct fs_db *fsdb, __u32 flags,
1879 char *tgtname, char *comment)
1881 struct mgs_thread_info *mgi = mgs_env_info(env);
1882 struct llog_cfg_rec *lcr;
1886 if (flags & CM_START)
1888 mgi->mgi_marker.cm_step = fsdb->fsdb_gen;
1889 mgi->mgi_marker.cm_flags = flags;
1890 mgi->mgi_marker.cm_vers = LUSTRE_VERSION_CODE;
1891 cplen = strlcpy(mgi->mgi_marker.cm_tgtname, tgtname,
1892 sizeof(mgi->mgi_marker.cm_tgtname));
1893 if (cplen >= sizeof(mgi->mgi_marker.cm_tgtname))
1895 cplen = strlcpy(mgi->mgi_marker.cm_comment, comment,
1896 sizeof(mgi->mgi_marker.cm_comment));
1897 if (cplen >= sizeof(mgi->mgi_marker.cm_comment))
1899 mgi->mgi_marker.cm_createtime = ktime_get_real_seconds();
1900 mgi->mgi_marker.cm_canceltime = 0;
1901 lustre_cfg_bufs_reset(&mgi->mgi_bufs, NULL);
1902 lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, &mgi->mgi_marker,
1903 sizeof(mgi->mgi_marker));
1904 lcr = lustre_cfg_rec_new(LCFG_MARKER, &mgi->mgi_bufs);
1908 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1909 lustre_cfg_rec_free(lcr);
1913 static int record_start_log(const struct lu_env *env, struct mgs_device *mgs,
1914 struct llog_handle **llh, char *name)
1916 static struct obd_uuid cfg_uuid = { .uuid = "config_uuid" };
1917 struct llog_ctxt *ctxt;
1922 GOTO(out, rc = -EBUSY);
1924 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
1926 GOTO(out, rc = -ENODEV);
1927 LASSERT(ctxt->loc_obd == mgs->mgs_obd);
1929 rc = llog_open_create(env, ctxt, llh, NULL, name);
1932 rc = llog_init_handle(env, *llh, LLOG_F_IS_PLAIN, &cfg_uuid);
1934 llog_close(env, *llh);
1936 llog_ctxt_put(ctxt);
1939 CERROR("%s: can't start log %s: rc = %d\n",
1940 mgs->mgs_obd->obd_name, name, rc);
1946 static int record_end_log(const struct lu_env *env, struct llog_handle **llh)
1950 rc = llog_close(env, *llh);
1956 /******************** config "macros" *********************/
1958 /* write an lcfg directly into a log (with markers) */
1959 static int mgs_write_log_direct(const struct lu_env *env,
1960 struct mgs_device *mgs, struct fs_db *fsdb,
1961 char *logname, struct llog_cfg_rec *lcr,
1962 char *devname, char *comment)
1964 struct llog_handle *llh = NULL;
1969 rc = record_start_log(env, mgs, &llh, logname);
1973 /* FIXME These should be a single journal transaction */
1974 rc = record_marker(env, llh, fsdb, CM_START, devname, comment);
1977 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1980 rc = record_marker(env, llh, fsdb, CM_END, devname, comment);
1984 record_end_log(env, &llh);
1988 /* write the lcfg in all logs for the given fs */
1989 static int mgs_write_log_direct_all(const struct lu_env *env,
1990 struct mgs_device *mgs,
1992 struct mgs_target_info *mti,
1993 struct llog_cfg_rec *lcr, char *devname,
1994 char *comment, int server_only)
1996 struct list_head log_list;
1997 struct mgs_direntry *dirent, *n;
1998 char *fsname = mti->mti_fsname;
1999 int rc = 0, len = strlen(fsname);
2002 /* Find all the logs in the CONFIGS directory */
2003 rc = class_dentry_readdir(env, mgs, &log_list);
2007 /* Could use fsdb index maps instead of directory listing */
2008 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
2009 list_del_init(&dirent->mde_list);
2010 /* don't write to sptlrpc rule log */
2011 if (strstr(dirent->mde_name, "-sptlrpc") != NULL)
2014 /* caller wants write server logs only */
2015 if (server_only && strstr(dirent->mde_name, "-client") != NULL)
2018 if (strlen(dirent->mde_name) <= len ||
2019 strncmp(fsname, dirent->mde_name, len) != 0 ||
2020 dirent->mde_name[len] != '-')
2023 CDEBUG(D_MGS, "Changing log %s\n", dirent->mde_name);
2024 /* Erase any old settings of this same parameter */
2025 rc = mgs_modify(env, mgs, fsdb, mti, dirent->mde_name,
2026 devname, comment, CM_SKIP);
2028 CERROR("%s: Can't modify llog %s: rc = %d\n",
2029 mgs->mgs_obd->obd_name, dirent->mde_name, rc);
2032 /* Write the new one */
2033 rc = mgs_write_log_direct(env, mgs, fsdb, dirent->mde_name,
2034 lcr, devname, comment);
2036 CERROR("%s: writing log %s: rc = %d\n",
2037 mgs->mgs_obd->obd_name, dirent->mde_name, rc);
2039 mgs_direntry_free(dirent);
2045 static int mgs_write_log_osp_to_mdt(const struct lu_env *env,
2046 struct mgs_device *mgs,
2048 struct mgs_target_info *mti,
2049 int index, char *logname);
2050 static int mgs_write_log_osc_to_lov(const struct lu_env *env,
2051 struct mgs_device *mgs,
2053 struct mgs_target_info *mti,
2054 char *logname, char *suffix, char *lovname,
2055 enum lustre_sec_part sec_part, int flags);
2056 static int name_create_mdt_and_lov(char **logname, char **lovname,
2057 struct fs_db *fsdb, int i);
2059 static int add_param(char *params, char *key, char *val)
2061 char *start = params + strlen(params);
2062 char *end = params + sizeof(((struct mgs_target_info *)0)->mti_params);
2066 keylen = strlen(key);
2067 if (start + 1 + keylen + strlen(val) >= end) {
2068 CERROR("params are too long: %s %s%s\n",
2069 params, key != NULL ? key : "", val);
2073 sprintf(start, " %s%s", key != NULL ? key : "", val);
2078 * Walk through client config log record and convert the related records
2081 static int mgs_steal_client_llog_handler(const struct lu_env *env,
2082 struct llog_handle *llh,
2083 struct llog_rec_hdr *rec, void *data)
2085 struct mgs_device *mgs;
2086 struct obd_device *obd;
2087 struct mgs_target_info *mti, *tmti;
2089 int cfg_len = rec->lrh_len;
2090 char *cfg_buf = (char*) (rec + 1);
2091 struct lustre_cfg *lcfg;
2093 struct llog_handle *mdt_llh = NULL;
2094 static int got_an_osc_or_mdc = 0;
2095 /* 0: not found any osc/mdc;
2099 static int last_step = -1;
2104 mti = ((struct temp_comp*)data)->comp_mti;
2105 tmti = ((struct temp_comp*)data)->comp_tmti;
2106 fsdb = ((struct temp_comp*)data)->comp_fsdb;
2107 obd = ((struct temp_comp *)data)->comp_obd;
2108 mgs = lu2mgs_dev(obd->obd_lu_dev);
2111 if (rec->lrh_type != OBD_CFG_REC) {
2112 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
2116 rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
2118 CERROR("Insane cfg\n");
2122 lcfg = (struct lustre_cfg *)cfg_buf;
2124 if (lcfg->lcfg_command == LCFG_MARKER) {
2125 struct cfg_marker *marker;
2126 marker = lustre_cfg_buf(lcfg, 1);
2127 if (!strncmp(marker->cm_comment, "add osc", 7) &&
2128 (marker->cm_flags & CM_START) &&
2129 !(marker->cm_flags & CM_SKIP)) {
2130 got_an_osc_or_mdc = 1;
2131 cplen = strlcpy(tmti->mti_svname, marker->cm_tgtname,
2132 sizeof(tmti->mti_svname));
2133 if (cplen >= sizeof(tmti->mti_svname))
2135 rc = record_start_log(env, mgs, &mdt_llh,
2139 rc = record_marker(env, mdt_llh, fsdb, CM_START,
2140 mti->mti_svname, "add osc(copied)");
2141 record_end_log(env, &mdt_llh);
2142 last_step = marker->cm_step;
2145 if (!strncmp(marker->cm_comment, "add osc", 7) &&
2146 (marker->cm_flags & CM_END) &&
2147 !(marker->cm_flags & CM_SKIP)) {
2148 LASSERT(last_step == marker->cm_step);
2150 got_an_osc_or_mdc = 0;
2151 memset(tmti, 0, sizeof(*tmti));
2152 rc = record_start_log(env, mgs, &mdt_llh,
2156 rc = record_marker(env, mdt_llh, fsdb, CM_END,
2157 mti->mti_svname, "add osc(copied)");
2158 record_end_log(env, &mdt_llh);
2161 if (!strncmp(marker->cm_comment, "add mdc", 7) &&
2162 (marker->cm_flags & CM_START) &&
2163 !(marker->cm_flags & CM_SKIP)) {
2164 got_an_osc_or_mdc = 2;
2165 last_step = marker->cm_step;
2166 memcpy(tmti->mti_svname, marker->cm_tgtname,
2167 strlen(marker->cm_tgtname));
2171 if (!strncmp(marker->cm_comment, "add mdc", 7) &&
2172 (marker->cm_flags & CM_END) &&
2173 !(marker->cm_flags & CM_SKIP)) {
2174 LASSERT(last_step == marker->cm_step);
2176 got_an_osc_or_mdc = 0;
2177 memset(tmti, 0, sizeof(*tmti));
2182 if (got_an_osc_or_mdc == 0 || last_step < 0)
2185 if (lcfg->lcfg_command == LCFG_ADD_UUID) {
2186 __u64 nodenid = lcfg->lcfg_nid;
2188 if (strlen(tmti->mti_uuid) == 0) {
2189 /* target uuid not set, this config record is before
2190 * LCFG_SETUP, this nid is one of target node nid.
2192 tmti->mti_nids[tmti->mti_nid_count] = nodenid;
2193 tmti->mti_nid_count++;
2195 char nidstr[LNET_NIDSTR_SIZE];
2197 /* failover node nid */
2198 libcfs_nid2str_r(nodenid, nidstr, sizeof(nidstr));
2199 rc = add_param(tmti->mti_params, PARAM_FAILNODE,
2206 if (lcfg->lcfg_command == LCFG_SETUP) {
2209 target = lustre_cfg_string(lcfg, 1);
2210 memcpy(tmti->mti_uuid, target, strlen(target));
2214 /* ignore client side sptlrpc_conf_log */
2215 if (lcfg->lcfg_command == LCFG_SPTLRPC_CONF)
2218 if (lcfg->lcfg_command == LCFG_ADD_MDC &&
2219 strstr(lustre_cfg_string(lcfg, 0), "-clilmv") != NULL) {
2222 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1)
2225 memcpy(tmti->mti_fsname, mti->mti_fsname,
2226 strlen(mti->mti_fsname));
2227 tmti->mti_stripe_index = index;
2229 rc = mgs_write_log_osp_to_mdt(env, mgs, fsdb, tmti,
2230 mti->mti_stripe_index,
2232 memset(tmti, 0, sizeof(*tmti));
2236 if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD) {
2239 char *logname, *lovname;
2241 rc = name_create_mdt_and_lov(&logname, &lovname, fsdb,
2242 mti->mti_stripe_index);
2245 sprintf(mdt_index, "-MDT%04x", mti->mti_stripe_index);
2247 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1) {
2248 name_destroy(&logname);
2249 name_destroy(&lovname);
2253 tmti->mti_stripe_index = index;
2254 rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, tmti, logname,
2257 name_destroy(&logname);
2258 name_destroy(&lovname);
2264 /* fsdb->fsdb_mutex is already held in mgs_write_log_target*/
2265 /* stealed from mgs_get_fsdb_from_llog*/
2266 static int mgs_steal_llog_for_mdt_from_client(const struct lu_env *env,
2267 struct mgs_device *mgs,
2269 struct temp_comp* comp)
2271 struct llog_handle *loghandle;
2272 struct mgs_target_info *tmti;
2273 struct llog_ctxt *ctxt;
2278 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
2279 LASSERT(ctxt != NULL);
2281 OBD_ALLOC_PTR(tmti);
2283 GOTO(out_ctxt, rc = -ENOMEM);
2285 comp->comp_tmti = tmti;
2286 comp->comp_obd = mgs->mgs_obd;
2288 rc = llog_open(env, ctxt, &loghandle, NULL, client_name,
2296 rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
2298 GOTO(out_close, rc);
2300 rc = llog_process_or_fork(env, loghandle, mgs_steal_client_llog_handler,
2301 (void *)comp, NULL, false);
2302 CDEBUG(D_MGS, "steal llog re = %d\n", rc);
2304 llog_close(env, loghandle);
2308 llog_ctxt_put(ctxt);
2312 /* lmv is the second thing for client logs */
2313 /* copied from mgs_write_log_lov. Please refer to that. */
2314 static int mgs_write_log_lmv(const struct lu_env *env,
2315 struct mgs_device *mgs,
2317 struct mgs_target_info *mti,
2318 char *logname, char *lmvname)
2320 struct llog_handle *llh = NULL;
2321 struct lmv_desc *lmvdesc;
2326 CDEBUG(D_MGS, "Writing lmv(%s) log for %s\n", lmvname,logname);
2328 OBD_ALLOC_PTR(lmvdesc);
2329 if (lmvdesc == NULL)
2331 lmvdesc->ld_active_tgt_count = 0;
2332 lmvdesc->ld_tgt_count = 0;
2333 sprintf((char*)lmvdesc->ld_uuid.uuid, "%s_UUID", lmvname);
2334 uuid = (char *)lmvdesc->ld_uuid.uuid;
2336 rc = record_start_log(env, mgs, &llh, logname);
2339 rc = record_marker(env, llh, fsdb, CM_START, lmvname, "lmv setup");
2342 rc = record_attach(env, llh, lmvname, "lmv", uuid);
2345 rc = record_lmv_setup(env, llh, lmvname, lmvdesc);
2348 rc = record_marker(env, llh, fsdb, CM_END, lmvname, "lmv setup");
2352 record_end_log(env, &llh);
2354 OBD_FREE_PTR(lmvdesc);
2358 /* lov is the first thing in the mdt and client logs */
2359 static int mgs_write_log_lov(const struct lu_env *env, struct mgs_device *mgs,
2360 struct fs_db *fsdb, struct mgs_target_info *mti,
2361 char *logname, char *lovname)
2363 struct llog_handle *llh = NULL;
2364 struct lov_desc *lovdesc;
2369 CDEBUG(D_MGS, "Writing lov(%s) log for %s\n", lovname, logname);
2372 #01 L attach 0:lov_mdsA 1:lov 2:71ccb_lov_mdsA_19f961a9e1
2373 #02 L lov_setup 0:lov_mdsA 1:(struct lov_desc)
2374 uuid=lov1_UUID, stripe count=1, size=1048576, offset=0, pattern=0
2377 /* FIXME just make lov_setup accept empty desc (put uuid in buf 2) */
2378 OBD_ALLOC_PTR(lovdesc);
2379 if (lovdesc == NULL)
2381 lovdesc->ld_magic = LOV_DESC_MAGIC;
2382 lovdesc->ld_tgt_count = 0;
2383 /* Defaults. Can be changed later by lcfg config_param */
2384 lovdesc->ld_default_stripe_count = 1;
2385 lovdesc->ld_pattern = LOV_PATTERN_RAID0;
2386 lovdesc->ld_default_stripe_size = LOV_DESC_STRIPE_SIZE_DEFAULT;
2387 lovdesc->ld_default_stripe_offset = -1;
2388 lovdesc->ld_qos_maxage = LOV_DESC_QOS_MAXAGE_DEFAULT;
2389 sprintf((char*)lovdesc->ld_uuid.uuid, "%s_UUID", lovname);
2390 /* can these be the same? */
2391 uuid = (char *)lovdesc->ld_uuid.uuid;
2393 /* This should always be the first entry in a log.
2394 rc = mgs_clear_log(obd, logname); */
2395 rc = record_start_log(env, mgs, &llh, logname);
2398 /* FIXME these should be a single journal transaction */
2399 rc = record_marker(env, llh, fsdb, CM_START, lovname, "lov setup");
2402 rc = record_attach(env, llh, lovname, "lov", uuid);
2405 rc = record_lov_setup(env, llh, lovname, lovdesc);
2408 rc = record_marker(env, llh, fsdb, CM_END, lovname, "lov setup");
2413 record_end_log(env, &llh);
2415 OBD_FREE_PTR(lovdesc);
2419 /* add failnids to open log */
2420 static int mgs_write_log_failnids(const struct lu_env *env,
2421 struct mgs_target_info *mti,
2422 struct llog_handle *llh,
2425 char *failnodeuuid = NULL;
2426 char *ptr = mti->mti_params;
2431 #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) nal=90 0: 1:uml1_UUID
2432 #04 L add_uuid nid=1@elan(0x1000000000001) nal=90 0: 1:uml1_UUID
2433 #05 L setup 0:OSC_uml1_ost1_mdsA 1:ost1_UUID 2:uml1_UUID
2434 #06 L add_uuid nid=uml2@tcp(0x20000c0a80202) nal=90 0: 1:uml2_UUID
2435 #0x L add_uuid nid=2@elan(0x1000000000002) nal=90 0: 1:uml2_UUID
2436 #07 L add_conn 0:OSC_uml1_ost1_mdsA 1:uml2_UUID
2440 * Pull failnid info out of params string, which may contain something
2441 * like "<nid1>,<nid2>:<nid3>,<nid4>". class_parse_nid() does not
2442 * complain about abnormal inputs like ",:<nid1>", "<nid1>:,<nid2>",
2443 * etc. However, convert_hostnames() should have caught those.
2445 while (class_find_param(ptr, PARAM_FAILNODE, &ptr) == 0) {
2446 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
2447 char nidstr[LNET_NIDSTR_SIZE];
2449 if (failnodeuuid == NULL) {
2450 /* We don't know the failover node name,
2451 * so just use the first nid as the uuid */
2452 libcfs_nid2str_r(nid, nidstr, sizeof(nidstr));
2453 rc = name_create(&failnodeuuid, nidstr, "");
2457 CDEBUG(D_MGS, "add nid %s for failover uuid %s, "
2459 libcfs_nid2str_r(nid, nidstr, sizeof(nidstr)),
2460 failnodeuuid, cliname);
2461 rc = record_add_uuid(env, llh, nid, failnodeuuid);
2463 * If *ptr is ':', we have added all NIDs for
2467 rc = record_add_conn(env, llh, cliname,
2469 name_destroy(&failnodeuuid);
2470 failnodeuuid = NULL;
2474 rc = record_add_conn(env, llh, cliname, failnodeuuid);
2475 name_destroy(&failnodeuuid);
2476 failnodeuuid = NULL;
2483 static int mgs_write_log_mdc_to_lmv(const struct lu_env *env,
2484 struct mgs_device *mgs,
2486 struct mgs_target_info *mti,
2487 char *logname, char *lmvname)
2489 struct llog_handle *llh = NULL;
2490 char *mdcname = NULL;
2491 char *nodeuuid = NULL;
2492 char *mdcuuid = NULL;
2493 char *lmvuuid = NULL;
2495 char nidstr[LNET_NIDSTR_SIZE];
2499 if (mgs_log_is_empty(env, mgs, logname)) {
2500 CERROR("log is empty! Logical error\n");
2504 CDEBUG(D_MGS, "adding mdc for %s to log %s:lmv(%s)\n",
2505 mti->mti_svname, logname, lmvname);
2507 libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2508 rc = name_create(&nodeuuid, nidstr, "");
2511 rc = name_create(&mdcname, mti->mti_svname, "-mdc");
2514 rc = name_create(&mdcuuid, mdcname, "_UUID");
2517 rc = name_create(&lmvuuid, lmvname, "_UUID");
2521 rc = record_start_log(env, mgs, &llh, logname);
2524 rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
2528 for (i = 0; i < mti->mti_nid_count; i++) {
2529 CDEBUG(D_MGS, "add nid %s for mdt\n",
2530 libcfs_nid2str_r(mti->mti_nids[i],
2531 nidstr, sizeof(nidstr)));
2533 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2538 rc = record_attach(env, llh, mdcname, LUSTRE_MDC_NAME, lmvuuid);
2541 rc = record_setup(env, llh, mdcname, mti->mti_uuid, nodeuuid,
2545 rc = mgs_write_log_failnids(env, mti, llh, mdcname);
2548 snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
2549 rc = record_mdc_add(env, llh, lmvname, mdcuuid, mti->mti_uuid,
2553 rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname,
2558 record_end_log(env, &llh);
2560 name_destroy(&lmvuuid);
2561 name_destroy(&mdcuuid);
2562 name_destroy(&mdcname);
2563 name_destroy(&nodeuuid);
2567 static inline int name_create_lov(char **lovname, char *mdtname,
2568 struct fs_db *fsdb, int index)
2571 if (index == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2572 return name_create(lovname, fsdb->fsdb_name, "-mdtlov");
2574 return name_create(lovname, mdtname, "-mdtlov");
2577 static int name_create_mdt_and_lov(char **logname, char **lovname,
2578 struct fs_db *fsdb, int i)
2582 rc = name_create_mdt(logname, fsdb->fsdb_name, i);
2586 if (i == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2587 rc = name_create(lovname, fsdb->fsdb_name, "-mdtlov");
2589 rc = name_create(lovname, *logname, "-mdtlov");
2591 name_destroy(logname);
2597 static inline int name_create_mdt_osc(char **oscname, char *ostname,
2598 struct fs_db *fsdb, int i)
2602 if (i == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2603 sprintf(suffix, "-osc");
2605 sprintf(suffix, "-osc-MDT%04x", i);
2606 return name_create(oscname, ostname, suffix);
2609 /* add new mdc to already existent MDS */
2610 static int mgs_write_log_osp_to_mdt(const struct lu_env *env,
2611 struct mgs_device *mgs,
2613 struct mgs_target_info *mti,
2614 int mdt_index, char *logname)
2616 struct llog_handle *llh = NULL;
2617 char *nodeuuid = NULL;
2618 char *ospname = NULL;
2619 char *lovuuid = NULL;
2620 char *mdtuuid = NULL;
2621 char *svname = NULL;
2622 char *mdtname = NULL;
2623 char *lovname = NULL;
2625 char nidstr[LNET_NIDSTR_SIZE];
2629 if (mgs_log_is_empty(env, mgs, mti->mti_svname)) {
2630 CERROR("log is empty! Logical error\n");
2634 CDEBUG(D_MGS, "adding osp index %d to %s\n", mti->mti_stripe_index,
2637 rc = name_create_mdt(&mdtname, fsdb->fsdb_name, mti->mti_stripe_index);
2641 libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2642 rc = name_create(&nodeuuid, nidstr, "");
2644 GOTO(out_destory, rc);
2646 rc = name_create(&svname, mdtname, "-osp");
2648 GOTO(out_destory, rc);
2650 sprintf(index_str, "-MDT%04x", mdt_index);
2651 rc = name_create(&ospname, svname, index_str);
2653 GOTO(out_destory, rc);
2655 rc = name_create_lov(&lovname, logname, fsdb, mdt_index);
2657 GOTO(out_destory, rc);
2659 rc = name_create(&lovuuid, lovname, "_UUID");
2661 GOTO(out_destory, rc);
2663 rc = name_create(&mdtuuid, mdtname, "_UUID");
2665 GOTO(out_destory, rc);
2667 rc = record_start_log(env, mgs, &llh, logname);
2669 GOTO(out_destory, rc);
2671 rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
2674 GOTO(out_destory, rc);
2676 for (i = 0; i < mti->mti_nid_count; i++) {
2677 CDEBUG(D_MGS, "add nid %s for mdt\n",
2678 libcfs_nid2str_r(mti->mti_nids[i],
2679 nidstr, sizeof(nidstr)));
2680 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2685 rc = record_attach(env, llh, ospname, LUSTRE_OSP_NAME, lovuuid);
2689 rc = record_setup(env, llh, ospname, mti->mti_uuid, nodeuuid,
2694 rc = mgs_write_log_failnids(env, mti, llh, ospname);
2698 /* Add mdc(osp) to lod */
2699 snprintf(index_str, sizeof(index_str), "%d", mti->mti_stripe_index);
2700 rc = record_base(env, llh, lovname, 0, LCFG_ADD_MDC, mti->mti_uuid,
2701 index_str, "1", NULL);
2705 rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname, "add osp");
2710 record_end_log(env, &llh);
2713 name_destroy(&mdtuuid);
2714 name_destroy(&lovuuid);
2715 name_destroy(&lovname);
2716 name_destroy(&ospname);
2717 name_destroy(&svname);
2718 name_destroy(&nodeuuid);
2719 name_destroy(&mdtname);
2723 static int mgs_write_log_mdt0(const struct lu_env *env,
2724 struct mgs_device *mgs,
2726 struct mgs_target_info *mti)
2728 char *log = mti->mti_svname;
2729 struct llog_handle *llh = NULL;
2730 struct obd_uuid *uuid;
2733 char *ptr = mti->mti_params;
2734 int rc = 0, failout = 0;
2737 OBD_ALLOC_PTR(uuid);
2741 if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
2742 failout = (strncmp(ptr, "failout", 7) == 0);
2744 rc = name_create(&lovname, log, "-mdtlov");
2747 if (mgs_log_is_empty(env, mgs, log)) {
2748 rc = mgs_write_log_lov(env, mgs, fsdb, mti, log, lovname);
2753 sprintf(mdt_index, "%d", mti->mti_stripe_index);
2755 rc = record_start_log(env, mgs, &llh, log);
2759 /* add MDT itself */
2761 /* FIXME this whole fn should be a single journal transaction */
2762 sprintf(uuid->uuid, "%s_UUID", log);
2763 rc = record_marker(env, llh, fsdb, CM_START, log, "add mdt");
2766 rc = record_attach(env, llh, log, LUSTRE_MDT_NAME, uuid->uuid);
2769 rc = record_mount_opt(env, llh, log, lovname, NULL);
2772 rc = record_setup(env, llh, log, uuid->uuid, mdt_index, lovname,
2773 failout ? "n" : "f");
2776 rc = record_marker(env, llh, fsdb, CM_END, log, "add mdt");
2780 record_end_log(env, &llh);
2782 name_destroy(&lovname);
2788 /* envelope method for all layers log */
2789 static int mgs_write_log_mdt(const struct lu_env *env,
2790 struct mgs_device *mgs,
2792 struct mgs_target_info *mti)
2794 struct mgs_thread_info *mgi = mgs_env_info(env);
2795 struct llog_handle *llh = NULL;
2800 CDEBUG(D_MGS, "writing new mdt %s\n", mti->mti_svname);
2802 if (mti->mti_uuid[0] == '\0') {
2803 /* Make up our own uuid */
2804 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
2805 "%s_UUID", mti->mti_svname);
2809 rc = mgs_write_log_mdt0(env, mgs, fsdb, mti);
2812 /* Append the mdt info to the client log */
2813 rc = name_create(&cliname, mti->mti_fsname, "-client");
2817 if (mgs_log_is_empty(env, mgs, cliname)) {
2818 /* Start client log */
2819 rc = mgs_write_log_lov(env, mgs, fsdb, mti, cliname,
2823 rc = mgs_write_log_lmv(env, mgs, fsdb, mti, cliname,
2830 #09 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0: 1:uml1_UUID
2831 #10 L attach 0:MDC_uml1_mdsA_MNT_client 1:mdc 2:1d834_MNT_client_03f
2832 #11 L setup 0:MDC_uml1_mdsA_MNT_client 1:mdsA_UUID 2:uml1_UUID
2833 #12 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0: 1:uml2_UUID
2834 #13 L add_conn 0:MDC_uml1_mdsA_MNT_client 1:uml2_UUID
2835 #14 L mount_option 0: 1:client 2:lov1 3:MDC_uml1_mdsA_MNT_client
2838 /* copy client info about lov/lmv */
2839 mgi->mgi_comp.comp_mti = mti;
2840 mgi->mgi_comp.comp_fsdb = fsdb;
2842 rc = mgs_steal_llog_for_mdt_from_client(env, mgs, cliname,
2846 rc = mgs_write_log_mdc_to_lmv(env, mgs, fsdb, mti, cliname,
2852 rc = record_start_log(env, mgs, &llh, cliname);
2856 rc = record_marker(env, llh, fsdb, CM_START, cliname, "mount opts");
2859 rc = record_mount_opt(env, llh, cliname, fsdb->fsdb_clilov,
2863 rc = record_marker(env, llh, fsdb, CM_END, cliname, "mount opts");
2867 /* for_all_existing_mdt except current one */
2868 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
2869 if (i != mti->mti_stripe_index &&
2870 test_bit(i, fsdb->fsdb_mdt_index_map)) {
2873 rc = name_create_mdt(&logname, fsdb->fsdb_name, i);
2877 /* NB: If the log for the MDT is empty, it means
2878 * the MDT is only added to the index
2879 * map, and not being process yet, i.e. this
2880 * is an unregistered MDT, see mgs_write_log_target().
2881 * so we should skip it. Otherwise
2883 * 1. MGS get register request for MDT1 and MDT2.
2885 * 2. Then both MDT1 and MDT2 are added into
2886 * fsdb_mdt_index_map. (see mgs_set_index()).
2888 * 3. Then MDT1 get the lock of fsdb_mutex, then
2889 * generate the config log, here, it will regard MDT2
2890 * as an existent MDT, and generate "add osp" for
2891 * lustre-MDT0001-osp-MDT0002. Note: at the moment
2892 * MDT0002 config log is still empty, so it will
2893 * add "add osp" even before "lov setup", which
2894 * will definitly cause trouble.
2896 * 4. MDT1 registeration finished, fsdb_mutex is
2897 * released, then MDT2 get in, then in above
2898 * mgs_steal_llog_for_mdt_from_client(), it will
2899 * add another osp log for lustre-MDT0001-osp-MDT0002,
2900 * which will cause another trouble.*/
2901 if (!mgs_log_is_empty(env, mgs, logname))
2902 rc = mgs_write_log_osp_to_mdt(env, mgs, fsdb,
2905 name_destroy(&logname);
2911 record_end_log(env, &llh);
2913 name_destroy(&cliname);
2917 /* Add the ost info to the client/mdt lov */
2918 static int mgs_write_log_osc_to_lov(const struct lu_env *env,
2919 struct mgs_device *mgs, struct fs_db *fsdb,
2920 struct mgs_target_info *mti,
2921 char *logname, char *suffix, char *lovname,
2922 enum lustre_sec_part sec_part, int flags)
2924 struct llog_handle *llh = NULL;
2925 char *nodeuuid = NULL;
2926 char *oscname = NULL;
2927 char *oscuuid = NULL;
2928 char *lovuuid = NULL;
2929 char *svname = NULL;
2931 char nidstr[LNET_NIDSTR_SIZE];
2935 CDEBUG(D_INFO, "adding osc for %s to log %s\n",
2936 mti->mti_svname, logname);
2938 if (mgs_log_is_empty(env, mgs, logname)) {
2939 CERROR("log is empty! Logical error\n");
2943 libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2944 rc = name_create(&nodeuuid, nidstr, "");
2947 rc = name_create(&svname, mti->mti_svname, "-osc");
2951 /* for the system upgraded from old 1.8, keep using the old osc naming
2952 * style for mdt, see name_create_mdt_osc(). LU-1257 */
2953 if (test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2954 rc = name_create(&oscname, svname, "");
2956 rc = name_create(&oscname, svname, suffix);
2960 rc = name_create(&oscuuid, oscname, "_UUID");
2963 rc = name_create(&lovuuid, lovname, "_UUID");
2969 #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0: 1:uml1_UUID
2971 #04 L add_uuid nid=1@elan(0x1000000000001) nal=90 0: 1:uml1_UUID
2972 #04 L attach 0:OSC_uml1_ost1_MNT_client 1:osc 2:89070_lov1_a41dff51a
2973 #05 L setup 0:OSC_uml1_ost1_MNT_client 1:ost1_UUID 2:uml1_UUID
2975 #06 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0: 1:uml2_UUID
2976 #07 L add_conn 0:OSC_uml1_ost1_MNT_client 1:uml2_UUID
2977 #08 L lov_modify_tgts add 0:lov1 1:ost1_UUID 2(index):0 3(gen):1
2980 rc = record_start_log(env, mgs, &llh, logname);
2984 /* FIXME these should be a single journal transaction */
2985 rc = record_marker(env, llh, fsdb, CM_START | flags, mti->mti_svname,
2990 /* NB: don't change record order, because upon MDT steal OSC config
2991 * from client, it treats all nids before LCFG_SETUP as target nids
2992 * (multiple interfaces), while nids after as failover node nids.
2993 * See mgs_steal_client_llog_handler() LCFG_ADD_UUID.
2995 for (i = 0; i < mti->mti_nid_count; i++) {
2996 CDEBUG(D_MGS, "add nid %s\n",
2997 libcfs_nid2str_r(mti->mti_nids[i],
2998 nidstr, sizeof(nidstr)));
2999 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
3003 rc = record_attach(env, llh, oscname, LUSTRE_OSC_NAME, lovuuid);
3006 rc = record_setup(env, llh, oscname, mti->mti_uuid, nodeuuid,
3010 rc = mgs_write_log_failnids(env, mti, llh, oscname);
3014 snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
3016 rc = record_lov_add(env, llh, lovname, mti->mti_uuid, index, "1");
3019 rc = record_marker(env, llh, fsdb, CM_END | flags, mti->mti_svname,
3024 record_end_log(env, &llh);
3026 name_destroy(&lovuuid);
3027 name_destroy(&oscuuid);
3028 name_destroy(&oscname);
3029 name_destroy(&svname);
3030 name_destroy(&nodeuuid);
3034 static int mgs_write_log_ost(const struct lu_env *env,
3035 struct mgs_device *mgs, struct fs_db *fsdb,
3036 struct mgs_target_info *mti)
3038 struct llog_handle *llh = NULL;
3039 char *logname, *lovname;
3040 char *ptr = mti->mti_params;
3041 int rc, flags = 0, failout = 0, i;
3044 CDEBUG(D_MGS, "writing new ost %s\n", mti->mti_svname);
3046 /* The ost startup log */
3048 /* If the ost log already exists, that means that someone reformatted
3049 the ost and it called target_add again. */
3050 if (!mgs_log_is_empty(env, mgs, mti->mti_svname)) {
3051 LCONSOLE_ERROR_MSG(0x141, "The config log for %s already "
3052 "exists, yet the server claims it never "
3053 "registered. It may have been reformatted, "
3054 "or the index changed. writeconf the MDT to "
3055 "regenerate all logs.\n", mti->mti_svname);
3060 attach obdfilter ost1 ost1_UUID
3061 setup /dev/loop2 ldiskfs f|n errors=remount-ro,user_xattr
3063 if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
3064 failout = (strncmp(ptr, "failout", 7) == 0);
3065 rc = record_start_log(env, mgs, &llh, mti->mti_svname);
3068 /* FIXME these should be a single journal transaction */
3069 rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,"add ost");
3072 if (*mti->mti_uuid == '\0')
3073 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
3074 "%s_UUID", mti->mti_svname);
3075 rc = record_attach(env, llh, mti->mti_svname,
3076 "obdfilter"/*LUSTRE_OST_NAME*/, mti->mti_uuid);
3079 rc = record_setup(env, llh, mti->mti_svname,
3080 "dev"/*ignored*/, "type"/*ignored*/,
3081 failout ? "n" : "f", NULL/*options*/);
3084 rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname, "add ost");
3088 record_end_log(env, &llh);
3091 /* We also have to update the other logs where this osc is part of
3094 if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
3095 /* If we're upgrading, the old mdt log already has our
3096 entry. Let's do a fake one for fun. */
3097 /* Note that we can't add any new failnids, since we don't
3098 know the old osc names. */
3099 flags = CM_SKIP | CM_UPGRADE146;
3101 } else if ((mti->mti_flags & LDD_F_UPDATE) != LDD_F_UPDATE) {
3102 /* If the update flag isn't set, don't update client/mdt
3105 LCONSOLE_WARN("Client log for %s was not updated; writeconf "
3106 "the MDT first to regenerate it.\n",
3110 /* Add ost to all MDT lov defs */
3111 for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
3112 if (test_bit(i, fsdb->fsdb_mdt_index_map)) {
3115 rc = name_create_mdt_and_lov(&logname, &lovname, fsdb,
3120 snprintf(mdt_index, sizeof(mdt_index), "-MDT%04x", i);
3121 rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, mti,
3123 lovname, LUSTRE_SP_MDT,
3125 name_destroy(&logname);
3126 name_destroy(&lovname);
3132 /* Append ost info to the client log */
3133 rc = name_create(&logname, mti->mti_fsname, "-client");
3136 if (mgs_log_is_empty(env, mgs, logname)) {
3137 /* Start client log */
3138 rc = mgs_write_log_lov(env, mgs, fsdb, mti, logname,
3142 rc = mgs_write_log_lmv(env, mgs, fsdb, mti, logname,
3147 rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, mti, logname, "",
3148 fsdb->fsdb_clilov, LUSTRE_SP_CLI, flags);
3150 name_destroy(&logname);
3154 static __inline__ int mgs_param_empty(char *ptr)
3158 if ((tmp = strchr(ptr, '=')) && (*(++tmp) == '\0'))
3163 static int mgs_write_log_failnid_internal(const struct lu_env *env,
3164 struct mgs_device *mgs,
3166 struct mgs_target_info *mti,
3167 char *logname, char *cliname)
3170 struct llog_handle *llh = NULL;
3172 if (mgs_param_empty(mti->mti_params)) {
3173 /* Remove _all_ failnids */
3174 rc = mgs_modify(env, mgs, fsdb, mti, logname,
3175 mti->mti_svname, "add failnid", CM_SKIP);
3176 return rc < 0 ? rc : 0;
3179 /* Otherwise failover nids are additive */
3180 rc = record_start_log(env, mgs, &llh, logname);
3183 /* FIXME this should be a single journal transaction */
3184 rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
3188 rc = mgs_write_log_failnids(env, mti, llh, cliname);
3191 rc = record_marker(env, llh, fsdb, CM_END,
3192 mti->mti_svname, "add failnid");
3194 record_end_log(env, &llh);
3199 /* Add additional failnids to an existing log.
3200 The mdc/osc must have been added to logs first */
3201 /* tcp nids must be in dotted-quad ascii -
3202 we can't resolve hostnames from the kernel. */
3203 static int mgs_write_log_add_failnid(const struct lu_env *env,
3204 struct mgs_device *mgs,
3206 struct mgs_target_info *mti)
3208 char *logname, *cliname;
3212 /* FIXME we currently can't erase the failnids
3213 * given when a target first registers, since they aren't part of
3214 * an "add uuid" stanza
3217 /* Verify that we know about this target */
3218 if (mgs_log_is_empty(env, mgs, mti->mti_svname)) {
3219 LCONSOLE_ERROR_MSG(0x142, "The target %s has not registered "
3220 "yet. It must be started before failnids "
3221 "can be added.\n", mti->mti_svname);
3225 /* Create mdc/osc client name (e.g. lustre-OST0001-osc) */
3226 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
3227 rc = name_create(&cliname, mti->mti_svname, "-mdc");
3228 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
3229 rc = name_create(&cliname, mti->mti_svname, "-osc");
3236 /* Add failover nids to the client log */
3237 rc = name_create(&logname, mti->mti_fsname, "-client");
3239 name_destroy(&cliname);
3243 rc = mgs_write_log_failnid_internal(env, mgs, fsdb,mti,logname,cliname);
3244 name_destroy(&logname);
3245 name_destroy(&cliname);
3249 if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
3250 /* Add OST failover nids to the MDT logs as well */
3253 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
3254 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
3256 rc = name_create_mdt(&logname, mti->mti_fsname, i);
3259 rc = name_create_mdt_osc(&cliname, mti->mti_svname,
3262 name_destroy(&logname);
3265 rc = mgs_write_log_failnid_internal(env, mgs, fsdb,
3268 name_destroy(&cliname);
3269 name_destroy(&logname);
3278 static int mgs_wlp_lcfg(const struct lu_env *env,
3279 struct mgs_device *mgs, struct fs_db *fsdb,
3280 struct mgs_target_info *mti,
3281 char *logname, struct lustre_cfg_bufs *bufs,
3282 char *tgtname, char *ptr)
3284 char comment[MTI_NAME_MAXLEN];
3286 struct llog_cfg_rec *lcr;
3289 /* Erase any old settings of this same parameter */
3290 strlcpy(comment, ptr, sizeof(comment));
3291 /* But don't try to match the value. */
3292 tmp = strchr(comment, '=');
3295 /* FIXME we should skip settings that are the same as old values */
3296 rc = mgs_modify(env, mgs, fsdb, mti, logname, tgtname, comment,CM_SKIP);
3299 del = mgs_param_empty(ptr);
3301 LCONSOLE_INFO("%s parameter %s.%s in log %s\n", del ? "Disabling" : rc ?
3302 "Setting" : "Modifying", tgtname, comment, logname);
3304 /* mgs_modify() will return 1 if nothing had to be done */
3310 lustre_cfg_bufs_reset(bufs, tgtname);
3311 lustre_cfg_bufs_set_string(bufs, 1, ptr);
3312 if (mti->mti_flags & LDD_F_PARAM2)
3313 lustre_cfg_bufs_set_string(bufs, 2, LCTL_UPCALL);
3315 lcr = lustre_cfg_rec_new((mti->mti_flags & LDD_F_PARAM2) ?
3316 LCFG_SET_PARAM : LCFG_PARAM, bufs);
3320 rc = mgs_write_log_direct(env, mgs, fsdb, logname, lcr, tgtname,
3322 lustre_cfg_rec_free(lcr);
3326 /* write global variable settings into log */
3327 static int mgs_write_log_sys(const struct lu_env *env,
3328 struct mgs_device *mgs, struct fs_db *fsdb,
3329 struct mgs_target_info *mti, char *sys, char *ptr)
3331 struct mgs_thread_info *mgi = mgs_env_info(env);
3332 struct lustre_cfg *lcfg;
3333 struct llog_cfg_rec *lcr;
3335 int rc, cmd, convert = 1;
3337 if (class_match_param(ptr, PARAM_TIMEOUT, &tmp) == 0) {
3338 cmd = LCFG_SET_TIMEOUT;
3339 } else if (class_match_param(ptr, PARAM_LDLM_TIMEOUT, &tmp) == 0) {
3340 cmd = LCFG_SET_LDLM_TIMEOUT;
3341 /* Check for known params here so we can return error to lctl */
3342 } else if ((class_match_param(ptr, PARAM_AT_MIN, &tmp) == 0) ||
3343 (class_match_param(ptr, PARAM_AT_MAX, &tmp) == 0) ||
3344 (class_match_param(ptr, PARAM_AT_EXTRA, &tmp) == 0) ||
3345 (class_match_param(ptr, PARAM_AT_EARLY_MARGIN, &tmp) == 0) ||
3346 (class_match_param(ptr, PARAM_AT_HISTORY, &tmp) == 0)) {
3348 } else if (class_match_param(ptr, PARAM_JOBID_VAR, &tmp) == 0) {
3349 convert = 0; /* Don't convert string value to integer */
3355 if (mgs_param_empty(ptr))
3356 CDEBUG(D_MGS, "global '%s' removed\n", sys);
3358 CDEBUG(D_MGS, "global '%s' val=%s\n", sys, tmp);
3360 lustre_cfg_bufs_reset(&mgi->mgi_bufs, NULL);
3361 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, sys);
3362 if (!convert && *tmp != '\0')
3363 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 2, tmp);
3364 lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
3368 lcfg = &lcr->lcr_cfg;
3370 rc = kstrtouint(tmp, 0, &lcfg->lcfg_num);
3372 GOTO(out_rec_free, rc);
3377 /* truncate the comment to the parameter name */
3381 /* modify all servers and clients */
3382 rc = mgs_write_log_direct_all(env, mgs, fsdb, mti,
3383 *tmp == '\0' ? NULL : lcr,
3384 mti->mti_fsname, sys, 0);
3385 if (rc == 0 && *tmp != '\0') {
3387 case LCFG_SET_TIMEOUT:
3388 if (!obd_timeout_set || lcfg->lcfg_num > obd_timeout)
3389 class_process_config(lcfg);
3391 case LCFG_SET_LDLM_TIMEOUT:
3392 if (!ldlm_timeout_set || lcfg->lcfg_num > ldlm_timeout)
3393 class_process_config(lcfg);
3401 lustre_cfg_rec_free(lcr);
3405 /* write quota settings into log */
3406 static int mgs_write_log_quota(const struct lu_env *env, struct mgs_device *mgs,
3407 struct fs_db *fsdb, struct mgs_target_info *mti,
3408 char *quota, char *ptr)
3410 struct mgs_thread_info *mgi = mgs_env_info(env);
3411 struct llog_cfg_rec *lcr;
3414 int rc, cmd = LCFG_PARAM;
3416 /* support only 'meta' and 'data' pools so far */
3417 if (class_match_param(ptr, QUOTA_METAPOOL_NAME, &tmp) != 0 &&
3418 class_match_param(ptr, QUOTA_DATAPOOL_NAME, &tmp) != 0) {
3419 CERROR("parameter quota.%s isn't supported (only quota.mdt "
3420 "& quota.ost are)\n", ptr);
3425 CDEBUG(D_MGS, "global '%s' removed\n", quota);
3427 CDEBUG(D_MGS, "global '%s'\n", quota);
3429 if (strchr(tmp, 'u') == NULL && strchr(tmp, 'g') == NULL &&
3430 strchr(tmp, 'p') == NULL &&
3431 strcmp(tmp, "none") != 0) {
3432 CERROR("enable option(%s) isn't supported\n", tmp);
3437 lustre_cfg_bufs_reset(&mgi->mgi_bufs, mti->mti_fsname);
3438 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, quota);
3439 lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
3443 /* truncate the comment to the parameter name */
3448 /* XXX we duplicated quota enable information in all server
3449 * config logs, it should be moved to a separate config
3450 * log once we cleanup the config log for global param. */
3451 /* modify all servers */
3452 rc = mgs_write_log_direct_all(env, mgs, fsdb, mti,
3453 *tmp == '\0' ? NULL : lcr,
3454 mti->mti_fsname, quota, 1);
3456 lustre_cfg_rec_free(lcr);
3457 return rc < 0 ? rc : 0;
3460 static int mgs_srpc_set_param_disk(const struct lu_env *env,
3461 struct mgs_device *mgs,
3463 struct mgs_target_info *mti,
3466 struct mgs_thread_info *mgi = mgs_env_info(env);
3467 struct llog_cfg_rec *lcr;
3468 struct llog_handle *llh = NULL;
3470 char *comment, *ptr;
3476 ptr = strchr(param, '=');
3477 LASSERT(ptr != NULL);
3480 OBD_ALLOC(comment, len + 1);
3481 if (comment == NULL)
3483 strncpy(comment, param, len);
3484 comment[len] = '\0';
3487 lustre_cfg_bufs_reset(&mgi->mgi_bufs, mti->mti_svname);
3488 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, param);
3489 lcr = lustre_cfg_rec_new(LCFG_SPTLRPC_CONF, &mgi->mgi_bufs);
3491 GOTO(out_comment, rc = -ENOMEM);
3493 /* construct log name */
3494 rc = name_create(&logname, mti->mti_fsname, "-sptlrpc");
3498 if (mgs_log_is_empty(env, mgs, logname)) {
3499 rc = record_start_log(env, mgs, &llh, logname);
3502 record_end_log(env, &llh);
3505 /* obsolete old one */
3506 rc = mgs_modify(env, mgs, fsdb, mti, logname, mti->mti_svname,
3510 /* write the new one */
3511 rc = mgs_write_log_direct(env, mgs, fsdb, logname, lcr,
3512 mti->mti_svname, comment);
3514 CERROR("%s: error writing log %s: rc = %d\n",
3515 mgs->mgs_obd->obd_name, logname, rc);
3517 name_destroy(&logname);
3519 lustre_cfg_rec_free(lcr);
3521 OBD_FREE(comment, len + 1);
3525 static int mgs_srpc_set_param_udesc_mem(struct fs_db *fsdb,
3530 /* disable the adjustable udesc parameter for now, i.e. use default
3531 * setting that client always ship udesc to MDT if possible. to enable
3532 * it simply remove the following line */
3535 ptr = strchr(param, '=');
3540 if (strcmp(param, PARAM_SRPC_UDESC))
3543 if (strcmp(ptr, "yes") == 0) {
3544 set_bit(FSDB_UDESC, &fsdb->fsdb_flags);
3545 CWARN("Enable user descriptor shipping from client to MDT\n");
3546 } else if (strcmp(ptr, "no") == 0) {
3547 clear_bit(FSDB_UDESC, &fsdb->fsdb_flags);
3548 CWARN("Disable user descriptor shipping from client to MDT\n");
3556 CERROR("Invalid param: %s\n", param);
3560 static int mgs_srpc_set_param_mem(struct fs_db *fsdb,
3564 struct sptlrpc_rule rule;
3565 struct sptlrpc_rule_set *rset;
3569 if (strncmp(param, PARAM_SRPC, sizeof(PARAM_SRPC) - 1) != 0) {
3570 CERROR("Invalid sptlrpc parameter: %s\n", param);
3574 if (strncmp(param, PARAM_SRPC_UDESC,
3575 sizeof(PARAM_SRPC_UDESC) - 1) == 0) {
3576 RETURN(mgs_srpc_set_param_udesc_mem(fsdb, param));
3579 if (strncmp(param, PARAM_SRPC_FLVR, sizeof(PARAM_SRPC_FLVR) - 1) != 0) {
3580 CERROR("Invalid sptlrpc flavor parameter: %s\n", param);
3584 param += sizeof(PARAM_SRPC_FLVR) - 1;
3586 rc = sptlrpc_parse_rule(param, &rule);
3590 /* mgs rules implies must be mgc->mgs */
3591 if (test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
3592 if ((rule.sr_from != LUSTRE_SP_MGC &&
3593 rule.sr_from != LUSTRE_SP_ANY) ||
3594 (rule.sr_to != LUSTRE_SP_MGS &&
3595 rule.sr_to != LUSTRE_SP_ANY))
3599 /* preapre room for this coming rule. svcname format should be:
3600 * - fsname: general rule
3601 * - fsname-tgtname: target-specific rule
3603 if (strchr(svname, '-')) {
3604 struct mgs_tgt_srpc_conf *tgtconf;
3607 for (tgtconf = fsdb->fsdb_srpc_tgt; tgtconf != NULL;
3608 tgtconf = tgtconf->mtsc_next) {
3609 if (!strcmp(tgtconf->mtsc_tgt, svname)) {
3618 OBD_ALLOC_PTR(tgtconf);
3619 if (tgtconf == NULL)
3622 name_len = strlen(svname);
3624 OBD_ALLOC(tgtconf->mtsc_tgt, name_len + 1);
3625 if (tgtconf->mtsc_tgt == NULL) {
3626 OBD_FREE_PTR(tgtconf);
3629 memcpy(tgtconf->mtsc_tgt, svname, name_len);
3631 tgtconf->mtsc_next = fsdb->fsdb_srpc_tgt;
3632 fsdb->fsdb_srpc_tgt = tgtconf;
3635 rset = &tgtconf->mtsc_rset;
3636 } else if (strcmp(svname, MGSSELF_NAME) == 0) {
3637 /* put _mgs related srpc rule directly in mgs ruleset */
3638 rset = &fsdb->fsdb_mgs->mgs_lut.lut_sptlrpc_rset;
3640 rset = &fsdb->fsdb_srpc_gen;
3643 rc = sptlrpc_rule_set_merge(rset, &rule);
3648 static int mgs_srpc_set_param(const struct lu_env *env,
3649 struct mgs_device *mgs,
3651 struct mgs_target_info *mti,
3661 /* keep a copy of original param, which could be destroied
3663 copy_size = strlen(param) + 1;
3664 OBD_ALLOC(copy, copy_size);
3667 memcpy(copy, param, copy_size);
3669 rc = mgs_srpc_set_param_mem(fsdb, mti->mti_svname, param);
3673 /* previous steps guaranteed the syntax is correct */
3674 rc = mgs_srpc_set_param_disk(env, mgs, fsdb, mti, copy);
3678 if (test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
3680 * for mgs rules, make them effective immediately.
3682 LASSERT(fsdb->fsdb_srpc_tgt == NULL);
3683 sptlrpc_target_update_exp_flavor(mgs->mgs_obd,
3684 &fsdb->fsdb_srpc_gen);
3688 OBD_FREE(copy, copy_size);
3692 struct mgs_srpc_read_data {
3693 struct fs_db *msrd_fsdb;
3697 static int mgs_srpc_read_handler(const struct lu_env *env,
3698 struct llog_handle *llh,
3699 struct llog_rec_hdr *rec, void *data)
3701 struct mgs_srpc_read_data *msrd = data;
3702 struct cfg_marker *marker;
3703 struct lustre_cfg *lcfg = REC_DATA(rec);
3704 char *svname, *param;
3708 if (rec->lrh_type != OBD_CFG_REC) {
3709 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
3713 cfg_len = REC_DATA_LEN(rec);
3715 rc = lustre_cfg_sanity_check(lcfg, cfg_len);
3717 CERROR("Insane cfg\n");
3721 if (lcfg->lcfg_command == LCFG_MARKER) {
3722 marker = lustre_cfg_buf(lcfg, 1);
3724 if (marker->cm_flags & CM_START &&
3725 marker->cm_flags & CM_SKIP)
3726 msrd->msrd_skip = 1;
3727 if (marker->cm_flags & CM_END)
3728 msrd->msrd_skip = 0;
3733 if (msrd->msrd_skip)
3736 if (lcfg->lcfg_command != LCFG_SPTLRPC_CONF) {
3737 CERROR("invalid command (%x)\n", lcfg->lcfg_command);
3741 svname = lustre_cfg_string(lcfg, 0);
3742 if (svname == NULL) {
3743 CERROR("svname is empty\n");
3747 param = lustre_cfg_string(lcfg, 1);
3748 if (param == NULL) {
3749 CERROR("param is empty\n");
3753 rc = mgs_srpc_set_param_mem(msrd->msrd_fsdb, svname, param);
3755 CERROR("read sptlrpc record error (%d): %s\n", rc, param);
3760 int mgs_get_fsdb_srpc_from_llog(const struct lu_env *env,
3761 struct mgs_device *mgs,
3764 struct llog_handle *llh = NULL;
3765 struct llog_ctxt *ctxt;
3767 struct mgs_srpc_read_data msrd;
3771 /* construct log name */
3772 rc = name_create(&logname, fsdb->fsdb_name, "-sptlrpc");
3776 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
3777 LASSERT(ctxt != NULL);
3779 if (mgs_log_is_empty(env, mgs, logname))
3782 rc = llog_open(env, ctxt, &llh, NULL, logname,
3790 rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL);
3792 GOTO(out_close, rc);
3794 if (llog_get_size(llh) <= 1)
3795 GOTO(out_close, rc = 0);
3797 msrd.msrd_fsdb = fsdb;
3800 rc = llog_process(env, llh, mgs_srpc_read_handler, (void *)&msrd,
3804 llog_close(env, llh);
3806 llog_ctxt_put(ctxt);
3807 name_destroy(&logname);
3810 CERROR("failed to read sptlrpc config database: %d\n", rc);
3814 static int mgs_write_log_param2(const struct lu_env *env,
3815 struct mgs_device *mgs,
3817 struct mgs_target_info *mti, char *ptr)
3819 struct lustre_cfg_bufs bufs;
3823 CDEBUG(D_MGS, "next param '%s'\n", ptr);
3825 /* PARAM_MGSNODE and PARAM_NETWORK are set only when formating
3826 * or during the inital mount. It can never change after that.
3828 if (!class_match_param(ptr, PARAM_MGSNODE, NULL) ||
3829 !class_match_param(ptr, PARAM_NETWORK, NULL)) {
3834 /* Processed in mgs_write_log_ost. Another value that can't
3835 * be changed by lctl set_param -P.
3837 if (!class_match_param(ptr, PARAM_FAILMODE, NULL)) {
3838 LCONSOLE_ERROR_MSG(0x169,
3839 "%s can only be changed with tunefs.lustre and --writeconf\n",
3845 /* FIXME !!! Support for sptlrpc is incomplete. Currently the change
3846 * doesn't transmit to the client. See LU-7183.
3848 if (!class_match_param(ptr, PARAM_SRPC, NULL)) {
3849 rc = mgs_srpc_set_param(env, mgs, fsdb, mti, ptr);
3853 /* Can't use class_match_param since ptr doesn't start with
3854 * PARAM_FAILNODE. So we look for PARAM_FAILNODE contained in ptr.
3856 if (strstr(ptr, PARAM_FAILNODE)) {
3857 /* Add a failover nidlist. We already processed failovers
3858 * params for new targets in mgs_write_log_target.
3862 /* can't use wildcards with failover.node */
3863 if (strchr(ptr, '*')) {
3868 param = strstr(ptr, PARAM_FAILNODE);
3869 if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
3870 sizeof(mti->mti_params)) {
3875 CDEBUG(D_MGS, "Adding failnode with param %s\n",
3877 rc = mgs_write_log_add_failnid(env, mgs, fsdb, mti);
3881 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, PARAMS_FILENAME, &bufs,
3882 mti->mti_svname, ptr);
3887 /* Permanent settings of all parameters by writing into the appropriate
3888 * configuration logs.
3889 * A parameter with null value ("<param>='\0'") means to erase it out of
3892 static int mgs_write_log_param(const struct lu_env *env,
3893 struct mgs_device *mgs, struct fs_db *fsdb,
3894 struct mgs_target_info *mti, char *ptr)
3896 struct mgs_thread_info *mgi = mgs_env_info(env);
3902 /* For various parameter settings, we have to figure out which logs
3903 care about them (e.g. both mdt and client for lov settings) */
3904 CDEBUG(D_MGS, "next param '%s'\n", ptr);
3906 /* The params are stored in MOUNT_DATA_FILE and modified via
3907 tunefs.lustre, or set using lctl conf_param */
3909 /* Processed in lustre_start_mgc */
3910 if (class_match_param(ptr, PARAM_MGSNODE, NULL) == 0)
3913 /* Processed in ost/mdt */
3914 if (class_match_param(ptr, PARAM_NETWORK, NULL) == 0)
3917 /* Processed in mgs_write_log_ost */
3918 if (class_match_param(ptr, PARAM_FAILMODE, NULL) == 0) {
3919 if (mti->mti_flags & LDD_F_PARAM) {
3920 LCONSOLE_ERROR_MSG(0x169,
3921 "%s can only be changed with tunefs.lustre and --writeconf\n",
3928 if (class_match_param(ptr, PARAM_SRPC, NULL) == 0) {
3929 rc = mgs_srpc_set_param(env, mgs, fsdb, mti, ptr);
3933 if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
3934 /* Add a failover nidlist */
3936 /* We already processed failovers params for new
3937 targets in mgs_write_log_target */
3938 if (mti->mti_flags & LDD_F_PARAM) {
3939 CDEBUG(D_MGS, "Adding failnode\n");
3940 rc = mgs_write_log_add_failnid(env, mgs, fsdb, mti);
3945 if (class_match_param(ptr, PARAM_SYS, &tmp) == 0) {
3946 rc = mgs_write_log_sys(env, mgs, fsdb, mti, ptr, tmp);
3950 if (class_match_param(ptr, PARAM_QUOTA, &tmp) == 0) {
3951 rc = mgs_write_log_quota(env, mgs, fsdb, mti, ptr, tmp);
3955 if (class_match_param(ptr, PARAM_OSC PARAM_ACTIVE, &tmp) == 0 ||
3956 class_match_param(ptr, PARAM_MDC PARAM_ACTIVE, &tmp) == 0) {
3957 /* active=0 means off, anything else means on */
3958 int flag = (*tmp == '0') ? CM_EXCLUDE : 0;
3959 bool deactive_osc = memcmp(ptr, PARAM_OSC PARAM_ACTIVE,
3960 strlen(PARAM_OSC PARAM_ACTIVE)) == 0;
3963 if (!deactive_osc) {
3966 rc = server_name2index(mti->mti_svname, &index, NULL);
3971 LCONSOLE_ERROR_MSG(0x144, "%s: MDC0 can not be"
3972 " (de)activated.\n",
3974 GOTO(end, rc = -EPERM);
3978 LCONSOLE_WARN("Permanently %sactivating %s\n",
3979 flag ? "de" : "re", mti->mti_svname);
3981 rc = name_create(&logname, mti->mti_fsname, "-client");
3984 rc = mgs_modify(env, mgs, fsdb, mti, logname,
3986 deactive_osc ? "add osc" : "add mdc", flag);
3987 name_destroy(&logname);
3992 /* Add to all MDT logs for DNE */
3993 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
3994 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
3996 rc = name_create_mdt(&logname, mti->mti_fsname, i);
3999 rc = mgs_modify(env, mgs, fsdb, mti, logname,
4001 deactive_osc ? "add osc" : "add osp",
4003 name_destroy(&logname);
4009 LCONSOLE_ERROR_MSG(0x145,
4010 "Couldn't find %s in log (%d). No permanent changes were made to the config log.\n",
4011 mti->mti_svname, rc);
4012 if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags))
4013 LCONSOLE_ERROR_MSG(0x146,
4014 "This may be because the log is in the old 1.4 style. Consider --writeconf to update the logs.\n");
4017 /* Fall through to osc/mdc proc for deactivating live
4018 OSC/OSP on running MDT / clients. */
4020 /* Below here, let obd's XXX_process_config methods handle it */
4022 /* All lov. in proc */
4023 if (class_match_param(ptr, PARAM_LOV, NULL) == 0) {
4026 CDEBUG(D_MGS, "lov param %s\n", ptr);
4027 if (!(mti->mti_flags & LDD_F_SV_TYPE_MDT)) {
4028 LCONSOLE_ERROR_MSG(0x147, "LOV params must be "
4029 "set on the MDT, not %s. "
4036 if (mgs_log_is_empty(env, mgs, mti->mti_svname))
4037 GOTO(end, rc = -ENODEV);
4039 rc = name_create_mdt_and_lov(&logname, &mdtlovname, fsdb,
4040 mti->mti_stripe_index);
4043 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, mti->mti_svname,
4044 &mgi->mgi_bufs, mdtlovname, ptr);
4045 name_destroy(&logname);
4046 name_destroy(&mdtlovname);
4051 rc = name_create(&logname, mti->mti_fsname, "-client");
4054 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname, &mgi->mgi_bufs,
4055 fsdb->fsdb_clilov, ptr);
4056 name_destroy(&logname);
4060 /* All osc., mdc., llite. params in proc */
4061 if ((class_match_param(ptr, PARAM_OSC, NULL) == 0) ||
4062 (class_match_param(ptr, PARAM_MDC, NULL) == 0) ||
4063 (class_match_param(ptr, PARAM_LLITE, NULL) == 0)) {
4066 if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
4067 LCONSOLE_ERROR_MSG(0x148, "Upgraded client logs for %s"
4068 " cannot be modified. Consider"
4069 " updating the configuration with"
4072 GOTO(end, rc = -EINVAL);
4074 if (memcmp(ptr, PARAM_LLITE, strlen(PARAM_LLITE)) == 0) {
4075 rc = name_create(&cname, mti->mti_fsname, "-client");
4076 /* Add the client type to match the obdname in
4077 class_config_llog_handler */
4078 } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
4079 rc = name_create(&cname, mti->mti_svname, "-mdc");
4080 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
4081 rc = name_create(&cname, mti->mti_svname, "-osc");
4083 GOTO(end, rc = -EINVAL);
4088 /* Forbid direct update of llite root squash parameters.
4089 * These parameters are indirectly set via the MDT settings.
4091 if ((class_match_param(ptr, PARAM_LLITE, &tmp) == 0) &&
4092 ((memcmp(tmp, "root_squash=", 12) == 0) ||
4093 (memcmp(tmp, "nosquash_nids=", 14) == 0))) {
4094 LCONSOLE_ERROR("%s: root squash parameters can only "
4095 "be updated through MDT component\n",
4097 name_destroy(&cname);
4098 GOTO(end, rc = -EINVAL);
4101 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
4104 rc = name_create(&logname, mti->mti_fsname, "-client");
4106 name_destroy(&cname);
4109 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname, &mgi->mgi_bufs,
4112 /* osc params affect the MDT as well */
4113 if (!rc && (mti->mti_flags & LDD_F_SV_TYPE_OST)) {
4116 for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
4117 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
4119 name_destroy(&cname);
4120 rc = name_create_mdt_osc(&cname, mti->mti_svname,
4122 name_destroy(&logname);
4125 rc = name_create_mdt(&logname,
4126 mti->mti_fsname, i);
4129 if (!mgs_log_is_empty(env, mgs, logname)) {
4130 rc = mgs_wlp_lcfg(env, mgs, fsdb,
4140 /* For mdc activate/deactivate, it affects OSP on MDT as well */
4141 if (class_match_param(ptr, PARAM_MDC PARAM_ACTIVE, &tmp) == 0 &&
4144 char *lodname = NULL;
4145 char *param_str = NULL;
4149 /* replace mdc with osp */
4150 memcpy(ptr, PARAM_OSP, strlen(PARAM_OSP));
4151 rc = server_name2index(mti->mti_svname, &index, NULL);
4153 memcpy(ptr, PARAM_MDC, strlen(PARAM_MDC));
4157 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
4158 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
4164 name_destroy(&logname);
4165 rc = name_create_mdt(&logname, mti->mti_fsname,
4170 if (mgs_log_is_empty(env, mgs, logname))
4173 snprintf(suffix, sizeof(suffix), "-osp-MDT%04x",
4175 name_destroy(&cname);
4176 rc = name_create(&cname, mti->mti_svname,
4181 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,
4182 &mgi->mgi_bufs, cname, ptr);
4186 /* Add configuration log for noitfying LOD
4187 * to active/deactive the OSP. */
4188 name_destroy(¶m_str);
4189 rc = name_create(¶m_str, cname,
4190 (*tmp == '0') ? ".active=0" :
4195 name_destroy(&lodname);
4196 rc = name_create(&lodname, logname, "-mdtlov");
4200 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,
4201 &mgi->mgi_bufs, lodname,
4206 memcpy(ptr, PARAM_MDC, strlen(PARAM_MDC));
4207 name_destroy(&lodname);
4208 name_destroy(¶m_str);
4211 name_destroy(&logname);
4212 name_destroy(&cname);
4216 /* All mdt. params in proc */
4217 if (class_match_param(ptr, PARAM_MDT, &tmp) == 0) {
4221 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
4222 if (strncmp(mti->mti_svname, mti->mti_fsname,
4223 MTI_NAME_MAXLEN) == 0)
4224 /* device is unspecified completely? */
4225 rc = LDD_F_SV_TYPE_MDT | LDD_F_SV_ALL;
4227 rc = server_name2index(mti->mti_svname, &idx, NULL);
4230 if ((rc & LDD_F_SV_TYPE_MDT) == 0)
4232 if (rc & LDD_F_SV_ALL) {
4233 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
4235 fsdb->fsdb_mdt_index_map))
4237 rc = name_create_mdt(&logname,
4238 mti->mti_fsname, i);
4241 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti,
4242 logname, &mgi->mgi_bufs,
4244 name_destroy(&logname);
4249 if ((memcmp(tmp, "root_squash=", 12) == 0) ||
4250 (memcmp(tmp, "nosquash_nids=", 14) == 0)) {
4251 LCONSOLE_ERROR("%s: root squash parameters "
4252 "cannot be applied to a single MDT\n",
4254 GOTO(end, rc = -EINVAL);
4256 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti,
4257 mti->mti_svname, &mgi->mgi_bufs,
4258 mti->mti_svname, ptr);
4263 /* root squash settings are also applied to llite
4264 * config log (see LU-1778) */
4266 ((memcmp(tmp, "root_squash=", 12) == 0) ||
4267 (memcmp(tmp, "nosquash_nids=", 14) == 0))) {
4271 rc = name_create(&cname, mti->mti_fsname, "-client");
4274 rc = name_create(&logname, mti->mti_fsname, "-client");
4276 name_destroy(&cname);
4279 rc = name_create(&ptr2, PARAM_LLITE, tmp);
4281 name_destroy(&cname);
4282 name_destroy(&logname);
4285 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,
4286 &mgi->mgi_bufs, cname, ptr2);
4287 name_destroy(&ptr2);
4288 name_destroy(&logname);
4289 name_destroy(&cname);
4294 /* All mdd., ost. and osd. params in proc */
4295 if ((class_match_param(ptr, PARAM_MDD, NULL) == 0) ||
4296 (class_match_param(ptr, PARAM_LOD, NULL) == 0) ||
4297 (class_match_param(ptr, PARAM_OST, NULL) == 0) ||
4298 (class_match_param(ptr, PARAM_OSD, NULL) == 0)) {
4299 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
4300 if (mgs_log_is_empty(env, mgs, mti->mti_svname))
4301 GOTO(end, rc = -ENODEV);
4303 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, mti->mti_svname,
4304 &mgi->mgi_bufs, mti->mti_svname, ptr);
4308 LCONSOLE_WARN("Ignoring unrecognized param '%s'\n", ptr);
4312 CERROR("err %d on param '%s'\n", rc, ptr);
4317 int mgs_write_log_target(const struct lu_env *env, struct mgs_device *mgs,
4318 struct mgs_target_info *mti, struct fs_db *fsdb)
4325 /* set/check the new target index */
4326 rc = mgs_set_index(env, mgs, mti);
4330 if (rc == EALREADY) {
4331 LCONSOLE_WARN("Found index %d for %s, updating log\n",
4332 mti->mti_stripe_index, mti->mti_svname);
4333 /* We would like to mark old log sections as invalid
4334 and add new log sections in the client and mdt logs.
4335 But if we add new sections, then live clients will
4336 get repeat setup instructions for already running
4337 osc's. So don't update the client/mdt logs. */
4338 mti->mti_flags &= ~LDD_F_UPDATE;
4342 OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_WRITE_TARGET_DELAY, cfs_fail_val > 0 ?
4345 mutex_lock(&fsdb->fsdb_mutex);
4347 if (mti->mti_flags & (LDD_F_VIRGIN | LDD_F_WRITECONF)) {
4348 /* Generate a log from scratch */
4349 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
4350 rc = mgs_write_log_mdt(env, mgs, fsdb, mti);
4351 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
4352 rc = mgs_write_log_ost(env, mgs, fsdb, mti);
4354 CERROR("Unknown target type %#x, can't create log for %s\n",
4355 mti->mti_flags, mti->mti_svname);
4358 CERROR("Can't write logs for %s (%d)\n",
4359 mti->mti_svname, rc);
4363 /* Just update the params from tunefs in mgs_write_log_params */
4364 CDEBUG(D_MGS, "Update params for %s\n", mti->mti_svname);
4365 mti->mti_flags |= LDD_F_PARAM;
4368 /* allocate temporary buffer, where class_get_next_param will
4369 make copy of a current parameter */
4370 OBD_ALLOC(buf, strlen(mti->mti_params) + 1);
4372 GOTO(out_up, rc = -ENOMEM);
4373 params = mti->mti_params;
4374 while (params != NULL) {
4375 rc = class_get_next_param(¶ms, buf);
4378 /* there is no next parameter, that is
4383 CDEBUG(D_MGS, "remaining string: '%s', param: '%s'\n",
4385 rc = mgs_write_log_param(env, mgs, fsdb, mti, buf);
4390 OBD_FREE(buf, strlen(mti->mti_params) + 1);
4393 mutex_unlock(&fsdb->fsdb_mutex);
4397 int mgs_erase_log(const struct lu_env *env, struct mgs_device *mgs, char *name)
4399 struct llog_ctxt *ctxt;
4402 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
4404 CERROR("%s: MGS config context doesn't exist\n",
4405 mgs->mgs_obd->obd_name);
4408 rc = llog_erase(env, ctxt, NULL, name);
4409 /* llog may not exist */
4412 llog_ctxt_put(ctxt);
4416 CERROR("%s: failed to clear log %s: %d\n",
4417 mgs->mgs_obd->obd_name, name, rc);
4422 /* erase all logs for the given fs */
4423 int mgs_erase_logs(const struct lu_env *env, struct mgs_device *mgs,
4426 struct list_head log_list;
4427 struct mgs_direntry *dirent, *n;
4428 char barrier_name[20] = {};
4431 int rc, len = strlen(fsname);
4434 mutex_lock(&mgs->mgs_mutex);
4436 /* Find all the logs in the CONFIGS directory */
4437 rc = class_dentry_readdir(env, mgs, &log_list);
4439 mutex_unlock(&mgs->mgs_mutex);
4443 if (list_empty(&log_list)) {
4444 mutex_unlock(&mgs->mgs_mutex);
4448 snprintf(barrier_name, sizeof(barrier_name) - 1, "%s-%s",
4449 fsname, BARRIER_FILENAME);
4450 /* Delete the barrier fsdb */
4451 mgs_remove_fsdb_by_name(mgs, barrier_name);
4452 /* Delete the fs db */
4453 mgs_remove_fsdb_by_name(mgs, fsname);
4454 mutex_unlock(&mgs->mgs_mutex);
4456 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4457 list_del_init(&dirent->mde_list);
4458 suffix = strrchr(dirent->mde_name, '-');
4459 if (suffix != NULL) {
4460 if ((len == suffix - dirent->mde_name) &&
4461 (strncmp(fsname, dirent->mde_name, len) == 0)) {
4462 CDEBUG(D_MGS, "Removing log %s\n",
4464 mgs_erase_log(env, mgs, dirent->mde_name);
4468 mgs_direntry_free(dirent);
4477 /* list all logs for the given fs */
4478 int mgs_list_logs(const struct lu_env *env, struct mgs_device *mgs,
4479 struct obd_ioctl_data *data)
4481 struct list_head log_list;
4482 struct mgs_direntry *dirent, *n;
4488 /* Find all the logs in the CONFIGS directory */
4489 rc = class_dentry_readdir(env, mgs, &log_list);
4493 out = data->ioc_bulk;
4494 remains = data->ioc_inllen1;
4495 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4496 list_del_init(&dirent->mde_list);
4497 suffix = strrchr(dirent->mde_name, '-');
4498 if (suffix != NULL) {
4499 l = scnprintf(out, remains, "config_log: %s\n",
4504 mgs_direntry_free(dirent);
4511 struct mgs_lcfg_fork_data {
4512 struct lustre_cfg_bufs mlfd_bufs;
4513 struct mgs_device *mlfd_mgs;
4514 struct llog_handle *mlfd_llh;
4515 const char *mlfd_oldname;
4516 const char *mlfd_newname;
4520 static bool contain_valid_fsname(char *buf, const char *fsname,
4521 int buflen, int namelen)
4523 if (buflen < namelen)
4526 if (memcmp(buf, fsname, namelen) != 0)
4529 if (buf[namelen] != '\0' && buf[namelen] != '-')
4535 static int mgs_lcfg_fork_handler(const struct lu_env *env,
4536 struct llog_handle *o_llh,
4537 struct llog_rec_hdr *o_rec, void *data)
4539 struct mgs_lcfg_fork_data *mlfd = data;
4540 struct lustre_cfg_bufs *n_bufs = &mlfd->mlfd_bufs;
4541 struct lustre_cfg *o_lcfg = (struct lustre_cfg *)(o_rec + 1);
4542 struct llog_cfg_rec *lcr;
4544 char *n_buf = mlfd->mlfd_data;
4546 int o_namelen = strlen(mlfd->mlfd_oldname);
4547 int n_namelen = strlen(mlfd->mlfd_newname);
4548 int diff = n_namelen - o_namelen;
4549 __u32 cmd = o_lcfg->lcfg_command;
4550 __u32 cnt = o_lcfg->lcfg_bufcount;
4556 o_buf = lustre_cfg_buf(o_lcfg, 0);
4557 o_buflen = o_lcfg->lcfg_buflens[0];
4558 if (contain_valid_fsname(o_buf, mlfd->mlfd_oldname, o_buflen,
4560 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4561 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4562 o_buflen - o_namelen);
4563 lustre_cfg_bufs_reset(n_bufs, n_buf);
4564 n_buf += cfs_size_round(o_buflen + diff);
4566 lustre_cfg_bufs_reset(n_bufs, o_buflen != 0 ? o_buf : NULL);
4571 struct cfg_marker *o_marker;
4572 struct cfg_marker *n_marker;
4576 CDEBUG(D_MGS, "Unknown cfg marker entry with %d "
4581 /* buf[1] is marker */
4582 o_buf = lustre_cfg_buf(o_lcfg, 1);
4583 o_buflen = o_lcfg->lcfg_buflens[1];
4584 o_marker = (struct cfg_marker *)o_buf;
4585 if (!contain_valid_fsname(o_marker->cm_tgtname,
4587 sizeof(o_marker->cm_tgtname),
4589 lustre_cfg_bufs_set(n_bufs, 1, o_marker,
4594 n_marker = (struct cfg_marker *)n_buf;
4595 *n_marker = *o_marker;
4596 memcpy(n_marker->cm_tgtname, mlfd->mlfd_newname, n_namelen);
4597 tgt_namelen = strlen(o_marker->cm_tgtname);
4598 if (tgt_namelen > o_namelen)
4599 memcpy(n_marker->cm_tgtname + n_namelen,
4600 o_marker->cm_tgtname + o_namelen,
4601 tgt_namelen - o_namelen);
4602 n_marker->cm_tgtname[tgt_namelen + diff] = '\0';
4603 lustre_cfg_bufs_set(n_bufs, 1, n_marker, sizeof(*n_marker));
4607 case LCFG_SET_PARAM: {
4608 for (i = 1; i < cnt; i++)
4609 /* buf[i] is the param value, reuse it directly */
4610 lustre_cfg_bufs_set(n_bufs, i,
4611 lustre_cfg_buf(o_lcfg, i),
4612 o_lcfg->lcfg_buflens[i]);
4618 case LCFG_POOL_DEL: {
4619 if (cnt < 3 || cnt > 4) {
4620 CDEBUG(D_MGS, "Unknown cfg pool (%x) entry with %d "
4621 "buffers\n", cmd, cnt);
4625 /* buf[1] is fsname */
4626 o_buf = lustre_cfg_buf(o_lcfg, 1);
4627 o_buflen = o_lcfg->lcfg_buflens[1];
4628 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4629 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4630 o_buflen - o_namelen);
4631 lustre_cfg_bufs_set(n_bufs, 1, n_buf, o_buflen + diff);
4632 n_buf += cfs_size_round(o_buflen + diff);
4634 /* buf[2] is the pool name, reuse it directly */
4635 lustre_cfg_bufs_set(n_bufs, 2, lustre_cfg_buf(o_lcfg, 2),
4636 o_lcfg->lcfg_buflens[2]);
4641 /* buf[3] is ostname */
4642 o_buf = lustre_cfg_buf(o_lcfg, 3);
4643 o_buflen = o_lcfg->lcfg_buflens[3];
4644 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4645 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4646 o_buflen - o_namelen);
4647 lustre_cfg_bufs_set(n_bufs, 3, n_buf, o_buflen + diff);
4652 o_buflen = o_lcfg->lcfg_buflens[1];
4653 if (o_buflen == sizeof(struct lov_desc) ||
4654 o_buflen == sizeof(struct lmv_desc)) {
4660 o_buf = lustre_cfg_buf(o_lcfg, 1);
4661 if (o_buflen == sizeof(struct lov_desc)) {
4662 struct lov_desc *o_desc =
4663 (struct lov_desc *)o_buf;
4664 struct lov_desc *n_desc =
4665 (struct lov_desc *)n_buf;
4668 o_uuid = o_desc->ld_uuid.uuid;
4669 n_uuid = n_desc->ld_uuid.uuid;
4670 uuid_len = sizeof(o_desc->ld_uuid.uuid);
4672 struct lmv_desc *o_desc =
4673 (struct lmv_desc *)o_buf;
4674 struct lmv_desc *n_desc =
4675 (struct lmv_desc *)n_buf;
4678 o_uuid = o_desc->ld_uuid.uuid;
4679 n_uuid = n_desc->ld_uuid.uuid;
4680 uuid_len = sizeof(o_desc->ld_uuid.uuid);
4683 if (unlikely(!contain_valid_fsname(o_uuid,
4684 mlfd->mlfd_oldname, uuid_len,
4686 lustre_cfg_bufs_set(n_bufs, 1, o_buf,
4691 memcpy(n_uuid, mlfd->mlfd_newname, n_namelen);
4692 uuid_len = strlen(o_uuid);
4693 if (uuid_len > o_namelen)
4694 memcpy(n_uuid + n_namelen,
4696 uuid_len - o_namelen);
4697 n_uuid[uuid_len + diff] = '\0';
4698 lustre_cfg_bufs_set(n_bufs, 1, n_buf, o_buflen);
4700 } /* else case fall through */
4701 } /* else case fall through */
4705 for (i = 1; i < cnt; i++) {
4706 o_buflen = o_lcfg->lcfg_buflens[i];
4710 o_buf = lustre_cfg_buf(o_lcfg, i);
4711 if (!contain_valid_fsname(o_buf, mlfd->mlfd_oldname,
4712 o_buflen, o_namelen)) {
4713 lustre_cfg_bufs_set(n_bufs, i, o_buf, o_buflen);
4717 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4718 if (o_buflen == o_namelen) {
4719 lustre_cfg_bufs_set(n_bufs, i, n_buf,
4721 n_buf += cfs_size_round(n_namelen);
4725 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4726 o_buflen - o_namelen);
4727 lustre_cfg_bufs_set(n_bufs, i, n_buf, o_buflen + diff);
4728 n_buf += cfs_size_round(o_buflen + diff);
4734 lcr = lustre_cfg_rec_new(cmd, n_bufs);
4738 lcr->lcr_cfg = *o_lcfg;
4739 rc = llog_write(env, mlfd->mlfd_llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
4740 lustre_cfg_rec_free(lcr);
4745 static int mgs_lcfg_fork_one(const struct lu_env *env, struct mgs_device *mgs,
4746 struct mgs_direntry *mde, const char *oldname,
4747 const char *newname)
4749 struct llog_handle *old_llh = NULL;
4750 struct llog_handle *new_llh = NULL;
4751 struct llog_ctxt *ctxt = NULL;
4752 struct mgs_lcfg_fork_data *mlfd = NULL;
4753 char *name_buf = NULL;
4755 int old_namelen = strlen(oldname);
4756 int new_namelen = strlen(newname);
4760 name_buflen = mde->mde_len + new_namelen - old_namelen;
4761 OBD_ALLOC(name_buf, name_buflen);
4765 memcpy(name_buf, newname, new_namelen);
4766 memcpy(name_buf + new_namelen, mde->mde_name + old_namelen,
4767 mde->mde_len - old_namelen);
4769 CDEBUG(D_MGS, "Fork the config-log from %s to %s\n",
4770 mde->mde_name, name_buf);
4772 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
4775 rc = llog_open_create(env, ctxt, &new_llh, NULL, name_buf);
4779 rc = llog_init_handle(env, new_llh, LLOG_F_IS_PLAIN, NULL);
4783 if (unlikely(mgs_log_is_empty(env, mgs, mde->mde_name)))
4786 rc = llog_open(env, ctxt, &old_llh, NULL, mde->mde_name,
4791 rc = llog_init_handle(env, old_llh, LLOG_F_IS_PLAIN, NULL);
4795 new_llh->lgh_hdr->llh_tgtuuid = old_llh->lgh_hdr->llh_tgtuuid;
4797 OBD_ALLOC(mlfd, LLOG_MIN_CHUNK_SIZE);
4799 GOTO(out, rc = -ENOMEM);
4801 mlfd->mlfd_mgs = mgs;
4802 mlfd->mlfd_llh = new_llh;
4803 mlfd->mlfd_oldname = oldname;
4804 mlfd->mlfd_newname = newname;
4806 rc = llog_process(env, old_llh, mgs_lcfg_fork_handler, mlfd, NULL);
4807 OBD_FREE(mlfd, LLOG_MIN_CHUNK_SIZE);
4813 llog_close(env, old_llh);
4815 llog_close(env, new_llh);
4817 OBD_FREE(name_buf, name_buflen);
4819 llog_ctxt_put(ctxt);
4824 int mgs_lcfg_fork(const struct lu_env *env, struct mgs_device *mgs,
4825 const char *oldname, const char *newname)
4827 struct list_head log_list;
4828 struct mgs_direntry *dirent, *n;
4829 int olen = strlen(oldname);
4830 int nlen = strlen(newname);
4835 if (unlikely(!oldname || oldname[0] == '\0' ||
4836 !newname || newname[0] == '\0'))
4839 if (strcmp(oldname, newname) == 0)
4842 /* lock it to prevent fork/erase/register in parallel. */
4843 mutex_lock(&mgs->mgs_mutex);
4845 rc = class_dentry_readdir(env, mgs, &log_list);
4847 mutex_unlock(&mgs->mgs_mutex);
4851 if (list_empty(&log_list)) {
4852 mutex_unlock(&mgs->mgs_mutex);
4856 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4859 ptr = strrchr(dirent->mde_name, '-');
4861 int tlen = ptr - dirent->mde_name;
4864 strncmp(newname, dirent->mde_name, tlen) == 0)
4865 GOTO(out, rc = -EEXIST);
4868 strncmp(oldname, dirent->mde_name, tlen) == 0)
4872 list_del_init(&dirent->mde_list);
4873 mgs_direntry_free(dirent);
4876 if (list_empty(&log_list)) {
4877 mutex_unlock(&mgs->mgs_mutex);
4881 list_for_each_entry(dirent, &log_list, mde_list) {
4882 rc = mgs_lcfg_fork_one(env, mgs, dirent, oldname, newname);
4890 mutex_unlock(&mgs->mgs_mutex);
4892 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4893 list_del_init(&dirent->mde_list);
4894 mgs_direntry_free(dirent);
4897 if (rc && count > 0)
4898 mgs_erase_logs(env, mgs, newname);
4903 int mgs_lcfg_erase(const struct lu_env *env, struct mgs_device *mgs,
4909 if (unlikely(!fsname || fsname[0] == '\0'))
4912 rc = mgs_erase_logs(env, mgs, fsname);
4917 static int mgs_xattr_del(const struct lu_env *env, struct dt_object *obj)
4919 struct dt_device *dev;
4920 struct thandle *th = NULL;
4925 dev = container_of0(obj->do_lu.lo_dev, struct dt_device, dd_lu_dev);
4926 th = dt_trans_create(env, dev);
4928 RETURN(PTR_ERR(th));
4930 rc = dt_declare_xattr_del(env, obj, XATTR_TARGET_RENAME, th);
4934 rc = dt_trans_start_local(env, dev, th);
4938 dt_write_lock(env, obj, 0);
4939 rc = dt_xattr_del(env, obj, XATTR_TARGET_RENAME, th);
4944 dt_write_unlock(env, obj);
4947 dt_trans_stop(env, dev, th);
4952 int mgs_lcfg_rename(const struct lu_env *env, struct mgs_device *mgs)
4954 struct list_head log_list;
4955 struct mgs_direntry *dirent, *n;
4957 struct lu_buf buf = {
4959 .lb_len = sizeof(fsname)
4965 rc = class_dentry_readdir(env, mgs, &log_list);
4969 if (list_empty(&log_list))
4972 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4973 struct dt_object *o = NULL;
4978 list_del_init(&dirent->mde_list);
4979 ptr = strrchr(dirent->mde_name, '-');
4983 len = ptr - dirent->mde_name;
4984 if (unlikely(len >= sizeof(oldname))) {
4985 CDEBUG(D_MGS, "Skip invalid configuration file %s\n",
4990 o = local_file_find(env, mgs->mgs_los, mgs->mgs_configs_dir,
4994 CDEBUG(D_MGS, "Fail to locate file %s: rc = %d\n",
4995 dirent->mde_name, rc);
4999 rc = dt_xattr_get(env, o, &buf, XATTR_TARGET_RENAME);
5005 "Fail to get EA for %s: rc = %d\n",
5006 dirent->mde_name, rc);
5010 if (unlikely(rc == len &&
5011 memcmp(fsname, dirent->mde_name, len) == 0)) {
5012 /* The new fsname is the same as the old one. */
5013 rc = mgs_xattr_del(env, o);
5017 memcpy(oldname, dirent->mde_name, len);
5018 oldname[len] = '\0';
5020 rc = mgs_lcfg_fork_one(env, mgs, dirent, oldname, fsname);
5021 if (rc && rc != -EEXIST) {
5022 CDEBUG(D_MGS, "Fail to fork %s: rc = %d\n",
5023 dirent->mde_name, rc);
5027 rc = mgs_erase_log(env, mgs, dirent->mde_name);
5029 CDEBUG(D_MGS, "Fail to erase old %s: rc = %d\n",
5030 dirent->mde_name, rc);
5031 /* keep it there if failed to remove it. */
5036 if (o && !IS_ERR(o))
5037 lu_object_put(env, &o->do_lu);
5039 mgs_direntry_free(dirent);
5044 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
5045 list_del_init(&dirent->mde_list);
5046 mgs_direntry_free(dirent);
5052 /* Setup _mgs fsdb and log
5054 int mgs__mgs_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs)
5056 struct fs_db *fsdb = NULL;
5060 rc = mgs_find_or_make_fsdb(env, mgs, MGSSELF_NAME, &fsdb);
5062 mgs_put_fsdb(mgs, fsdb);
5067 /* Setup params fsdb and log
5069 int mgs_params_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs)
5071 struct fs_db *fsdb = NULL;
5072 struct llog_handle *params_llh = NULL;
5076 rc = mgs_find_or_make_fsdb(env, mgs, PARAMS_FILENAME, &fsdb);
5078 mutex_lock(&fsdb->fsdb_mutex);
5079 rc = record_start_log(env, mgs, ¶ms_llh, PARAMS_FILENAME);
5081 rc = record_end_log(env, ¶ms_llh);
5082 mutex_unlock(&fsdb->fsdb_mutex);
5083 mgs_put_fsdb(mgs, fsdb);
5089 /* Cleanup params fsdb and log
5091 int mgs_params_fsdb_cleanup(const struct lu_env *env, struct mgs_device *mgs)
5095 rc = mgs_erase_logs(env, mgs, PARAMS_FILENAME);
5096 return rc == -ENOENT ? 0 : rc;
5100 * Fill in the mgs_target_info based on data devname and param provide.
5102 * @env thread context
5104 * @mti mgs target info. We want to set this based other paramters
5105 * passed to this function. Once setup we write it to the config
5107 * @devname optional OBD device name
5108 * @param string that contains both what tunable to set and the value to
5111 * RETURN 0 for success
5112 * negative error number on failure
5114 static int mgs_set_conf_param(const struct lu_env *env, struct mgs_device *mgs,
5115 struct mgs_target_info *mti, const char *devname,
5118 struct fs_db *fsdb = NULL;
5123 /* lustre, lustre-mdtlov, lustre-client, lustre-MDT0000 */
5127 /* We have two possible cases here:
5129 * 1) the device name embedded in the param:
5130 * lustre-OST0000.osc.max_dirty_mb=32
5132 * 2) the file system name is embedded in
5133 * the param: lustre.sys.at.min=0
5135 len = strcspn(param, ".=");
5136 if (!len || param[len] == '=')
5139 if (len >= sizeof(mti->mti_svname))
5142 snprintf(mti->mti_svname, sizeof(mti->mti_svname),
5143 "%.*s", (int)len, param);
5146 if (strlcpy(mti->mti_svname, devname, sizeof(mti->mti_svname)) >=
5147 sizeof(mti->mti_svname))
5151 if (!strlen(mti->mti_svname)) {
5152 LCONSOLE_ERROR_MSG(0x14d, "No target specified: %s\n", param);
5156 dev_type = mgs_parse_devname(mti->mti_svname, mti->mti_fsname,
5157 &mti->mti_stripe_index);
5159 /* For this case we have an invalid obd device name */
5161 CDEBUG(D_MGS, "%s don't contain an index\n", mti->mti_svname);
5162 strlcpy(mti->mti_fsname, mti->mti_svname, MTI_NAME_MAXLEN);
5165 /* Not an obd device, assume devname is the fsname.
5166 * User might of only provided fsname and not obd device
5169 CDEBUG(D_MGS, "%s is seen as a file system name\n", mti->mti_svname);
5170 strlcpy(mti->mti_fsname, mti->mti_svname, MTI_NAME_MAXLEN);
5175 GOTO(out, rc = dev_type);
5177 /* param related to llite isn't allowed to set by OST or MDT */
5178 if (dev_type & LDD_F_SV_TYPE_OST ||
5179 dev_type & LDD_F_SV_TYPE_MDT) {
5180 /* param related to llite isn't allowed to set by OST
5183 if (!strncmp(param, PARAM_LLITE,
5184 sizeof(PARAM_LLITE) - 1))
5185 GOTO(out, rc = -EINVAL);
5187 /* Strip -osc or -mdc suffix from svname */
5188 if (server_make_name(dev_type, mti->mti_stripe_index,
5189 mti->mti_fsname, mti->mti_svname,
5190 sizeof(mti->mti_svname)))
5191 GOTO(out, rc = -EINVAL);
5196 if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
5197 sizeof(mti->mti_params))
5198 GOTO(out, rc = -E2BIG);
5200 CDEBUG(D_MGS, "set_conf_param fs='%s' device='%s' param='%s'\n",
5201 mti->mti_fsname, mti->mti_svname, mti->mti_params);
5203 rc = mgs_find_or_make_fsdb(env, mgs, mti->mti_fsname, &fsdb);
5207 if (!test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags) &&
5208 test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
5209 CERROR("No filesystem targets for %s. cfg_device from lctl "
5210 "is '%s'\n", mti->mti_fsname, mti->mti_svname);
5211 mgs_unlink_fsdb(mgs, fsdb);
5212 GOTO(out, rc = -EINVAL);
5216 * Revoke lock so everyone updates. Should be alright if
5217 * someone was already reading while we were updating the logs,
5218 * so we don't really need to hold the lock while we're
5221 mti->mti_flags = dev_type | LDD_F_PARAM;
5222 mutex_lock(&fsdb->fsdb_mutex);
5223 rc = mgs_write_log_param(env, mgs, fsdb, mti, mti->mti_params);
5224 mutex_unlock(&fsdb->fsdb_mutex);
5225 mgs_revoke_lock(mgs, fsdb, CONFIG_T_CONFIG);
5229 mgs_put_fsdb(mgs, fsdb);
5234 static int mgs_set_param2(const struct lu_env *env, struct mgs_device *mgs,
5235 struct mgs_target_info *mti, const char *param)
5237 struct fs_db *fsdb = NULL;
5242 if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
5243 sizeof(mti->mti_params))
5244 GOTO(out, rc = -E2BIG);
5246 len = strcspn(param, ".=");
5247 if (len && param[len] != '=') {
5248 struct list_head *tmp;
5252 ptr = strchr(param, '.');
5254 len = strlen(param);
5257 if (len >= sizeof(mti->mti_svname))
5258 GOTO(out, rc = -E2BIG);
5260 snprintf(mti->mti_svname, sizeof(mti->mti_svname), "%.*s",
5263 mutex_lock(&mgs->mgs_mutex);
5264 if (unlikely(list_empty(&mgs->mgs_fs_db_list))) {
5265 mutex_unlock(&mgs->mgs_mutex);
5266 GOTO(out, rc = -ENODEV);
5269 list_for_each(tmp, &mgs->mgs_fs_db_list) {
5270 fsdb = list_entry(tmp, struct fs_db, fsdb_list);
5271 if (fsdb->fsdb_has_lproc_entry &&
5272 strcmp(fsdb->fsdb_name, "params") != 0 &&
5273 strstr(param, fsdb->fsdb_name)) {
5274 snprintf(mti->mti_svname,
5275 sizeof(mti->mti_svname), "%s",
5283 snprintf(mti->mti_svname, sizeof(mti->mti_svname),
5286 mutex_unlock(&mgs->mgs_mutex);
5288 snprintf(mti->mti_svname, sizeof(mti->mti_svname), "general");
5291 CDEBUG(D_MGS, "set_param2 fs='%s' device='%s' param='%s'\n",
5292 mti->mti_fsname, mti->mti_svname, mti->mti_params);
5294 /* The return value should be the device type i.e LDD_F_SV_TYPE_XXX.
5295 * A returned error tells us we don't have a target obd device.
5297 dev_type = server_name2index(mti->mti_svname, &mti->mti_stripe_index,
5302 /* the return value should be the device type i.e LDD_F_SV_TYPE_XXX.
5303 * Strip -osc or -mdc suffix from svname
5305 if ((dev_type & LDD_F_SV_TYPE_OST || dev_type & LDD_F_SV_TYPE_MDT) &&
5306 server_make_name(dev_type, mti->mti_stripe_index,
5307 mti->mti_fsname, mti->mti_svname,
5308 sizeof(mti->mti_svname)))
5309 GOTO(out, rc = -EINVAL);
5311 rc = mgs_find_or_make_fsdb(env, mgs, PARAMS_FILENAME, &fsdb);
5315 * Revoke lock so everyone updates. Should be alright if
5316 * someone was already reading while we were updating the logs,
5317 * so we don't really need to hold the lock while we're
5320 mti->mti_flags = dev_type | LDD_F_PARAM2;
5321 mutex_lock(&fsdb->fsdb_mutex);
5322 rc = mgs_write_log_param2(env, mgs, fsdb, mti, mti->mti_params);
5323 mutex_unlock(&fsdb->fsdb_mutex);
5324 mgs_revoke_lock(mgs, fsdb, CONFIG_T_PARAMS);
5325 mgs_put_fsdb(mgs, fsdb);
5330 /* Set a permanent (config log) param for a target or fs
5332 * @lcfg buf0 may contain the device (testfs-MDT0000) name
5333 * buf1 contains the single parameter
5335 int mgs_set_param(const struct lu_env *env, struct mgs_device *mgs,
5336 struct lustre_cfg *lcfg)
5338 const char *param = lustre_cfg_string(lcfg, 1);
5339 struct mgs_target_info *mti;
5342 /* Create a fake mti to hold everything */
5347 print_lustre_cfg(lcfg);
5349 if (lcfg->lcfg_command == LCFG_PARAM) {
5350 /* For the case of lctl conf_param devname can be
5351 * lustre, lustre-mdtlov, lustre-client, lustre-MDT0000
5353 const char *devname = lustre_cfg_string(lcfg, 0);
5355 rc = mgs_set_conf_param(env, mgs, mti, devname, param);
5357 /* In the case of lctl set_param -P lcfg[0] will always
5358 * be 'general'. At least for now.
5360 rc = mgs_set_param2(env, mgs, mti, param);
5368 static int mgs_write_log_pool(const struct lu_env *env,
5369 struct mgs_device *mgs, char *logname,
5370 struct fs_db *fsdb, char *tgtname,
5371 enum lcfg_command_type cmd,
5372 char *fsname, char *poolname,
5373 char *ostname, char *comment)
5375 struct llog_handle *llh = NULL;
5378 rc = record_start_log(env, mgs, &llh, logname);
5381 rc = record_marker(env, llh, fsdb, CM_START, tgtname, comment);
5384 rc = record_base(env, llh, tgtname, 0, cmd,
5385 fsname, poolname, ostname, NULL);
5388 rc = record_marker(env, llh, fsdb, CM_END, tgtname, comment);
5390 record_end_log(env, &llh);
5394 int mgs_nodemap_cmd(const struct lu_env *env, struct mgs_device *mgs,
5395 enum lcfg_command_type cmd, const char *nodemap_name,
5406 case LCFG_NODEMAP_ADD:
5407 rc = nodemap_add(nodemap_name);
5409 case LCFG_NODEMAP_DEL:
5410 rc = nodemap_del(nodemap_name);
5412 case LCFG_NODEMAP_ADD_RANGE:
5413 rc = nodemap_parse_range(param, nid);
5416 rc = nodemap_add_range(nodemap_name, nid);
5418 case LCFG_NODEMAP_DEL_RANGE:
5419 rc = nodemap_parse_range(param, nid);
5422 rc = nodemap_del_range(nodemap_name, nid);
5424 case LCFG_NODEMAP_ADMIN:
5425 rc = kstrtobool(param, &bool_switch);
5428 rc = nodemap_set_allow_root(nodemap_name, bool_switch);
5430 case LCFG_NODEMAP_DENY_UNKNOWN:
5431 rc = kstrtobool(param, &bool_switch);
5434 rc = nodemap_set_deny_unknown(nodemap_name, bool_switch);
5436 case LCFG_NODEMAP_AUDIT_MODE:
5437 rc = kstrtoul(param, 10, (unsigned long *)&bool_switch);
5439 rc = nodemap_set_audit_mode(nodemap_name, bool_switch);
5441 case LCFG_NODEMAP_MAP_MODE:
5442 if (strcmp("both", param) == 0)
5443 rc = nodemap_set_mapping_mode(nodemap_name,
5445 else if (strcmp("uid_only", param) == 0)
5446 rc = nodemap_set_mapping_mode(nodemap_name,
5447 NODEMAP_MAP_UID_ONLY);
5448 else if (strcmp("gid_only", param) == 0)
5449 rc = nodemap_set_mapping_mode(nodemap_name,
5450 NODEMAP_MAP_GID_ONLY);
5454 case LCFG_NODEMAP_TRUSTED:
5455 rc = kstrtobool(param, &bool_switch);
5458 rc = nodemap_set_trust_client_ids(nodemap_name, bool_switch);
5460 case LCFG_NODEMAP_SQUASH_UID:
5461 rc = kstrtouint(param, 10, &int_id);
5464 rc = nodemap_set_squash_uid(nodemap_name, int_id);
5466 case LCFG_NODEMAP_SQUASH_GID:
5467 rc = kstrtouint(param, 10, &int_id);
5470 rc = nodemap_set_squash_gid(nodemap_name, int_id);
5472 case LCFG_NODEMAP_ADD_UIDMAP:
5473 case LCFG_NODEMAP_ADD_GIDMAP:
5474 rc = nodemap_parse_idmap(param, idmap);
5477 if (cmd == LCFG_NODEMAP_ADD_UIDMAP)
5478 rc = nodemap_add_idmap(nodemap_name, NODEMAP_UID,
5481 rc = nodemap_add_idmap(nodemap_name, NODEMAP_GID,
5484 case LCFG_NODEMAP_DEL_UIDMAP:
5485 case LCFG_NODEMAP_DEL_GIDMAP:
5486 rc = nodemap_parse_idmap(param, idmap);
5489 if (cmd == LCFG_NODEMAP_DEL_UIDMAP)
5490 rc = nodemap_del_idmap(nodemap_name, NODEMAP_UID,
5493 rc = nodemap_del_idmap(nodemap_name, NODEMAP_GID,
5496 case LCFG_NODEMAP_SET_FILESET:
5497 rc = nodemap_set_fileset(nodemap_name, param);
5499 case LCFG_NODEMAP_SET_SEPOL:
5500 rc = nodemap_set_sepol(nodemap_name, param);
5509 int mgs_pool_cmd(const struct lu_env *env, struct mgs_device *mgs,
5510 enum lcfg_command_type cmd, char *fsname,
5511 char *poolname, char *ostname)
5516 char *label = NULL, *canceled_label = NULL;
5518 struct mgs_target_info *mti = NULL;
5519 bool checked = false;
5520 bool locked = false;
5525 rc = mgs_find_or_make_fsdb(env, mgs, fsname, &fsdb);
5527 CERROR("Can't get db for %s\n", fsname);
5530 if (test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
5531 CERROR("%s is not defined\n", fsname);
5533 GOTO(out_fsdb, rc = -EINVAL);
5536 label_sz = 10 + strlen(fsname) + strlen(poolname);
5538 /* check if ostname match fsname */
5539 if (ostname != NULL) {
5542 ptr = strrchr(ostname, '-');
5543 if ((ptr == NULL) ||
5544 (strncmp(fsname, ostname, ptr-ostname) != 0))
5546 label_sz += strlen(ostname);
5549 OBD_ALLOC(label, label_sz);
5551 GOTO(out_fsdb, rc = -ENOMEM);
5556 "new %s.%s", fsname, poolname);
5560 "add %s.%s.%s", fsname, poolname, ostname);
5563 OBD_ALLOC(canceled_label, label_sz);
5564 if (canceled_label == NULL)
5565 GOTO(out_label, rc = -ENOMEM);
5567 "rem %s.%s.%s", fsname, poolname, ostname);
5568 sprintf(canceled_label,
5569 "add %s.%s.%s", fsname, poolname, ostname);
5572 OBD_ALLOC(canceled_label, label_sz);
5573 if (canceled_label == NULL)
5574 GOTO(out_label, rc = -ENOMEM);
5576 "del %s.%s", fsname, poolname);
5577 sprintf(canceled_label,
5578 "new %s.%s", fsname, poolname);
5586 GOTO(out_cancel, rc = -ENOMEM);
5587 strncpy(mti->mti_svname, "lov pool", sizeof(mti->mti_svname));
5589 mutex_lock(&fsdb->fsdb_mutex);
5591 /* write pool def to all MDT logs */
5592 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
5593 if (test_bit(i, fsdb->fsdb_mdt_index_map)) {
5594 rc = name_create_mdt_and_lov(&logname, &lovname,
5599 if (!checked && (canceled_label == NULL)) {
5600 rc = mgs_check_marker(env, mgs, fsdb, mti,
5601 logname, lovname, label);
5603 name_destroy(&logname);
5604 name_destroy(&lovname);
5606 rc = (rc == LLOG_PROC_BREAK ?
5611 if (canceled_label != NULL)
5612 rc = mgs_modify(env, mgs, fsdb, mti, logname,
5613 lovname, canceled_label,
5617 rc = mgs_write_log_pool(env, mgs, logname,
5621 name_destroy(&logname);
5622 name_destroy(&lovname);
5628 rc = name_create(&logname, fsname, "-client");
5632 if (!checked && (canceled_label == NULL)) {
5633 rc = mgs_check_marker(env, mgs, fsdb, mti, logname,
5634 fsdb->fsdb_clilov, label);
5636 name_destroy(&logname);
5637 GOTO(out_mti, rc = (rc == LLOG_PROC_BREAK ?
5641 if (canceled_label != NULL) {
5642 rc = mgs_modify(env, mgs, fsdb, mti, logname,
5643 fsdb->fsdb_clilov, canceled_label, CM_SKIP);
5645 name_destroy(&logname);
5650 rc = mgs_write_log_pool(env, mgs, logname, fsdb, fsdb->fsdb_clilov,
5651 cmd, fsname, poolname, ostname, label);
5652 mutex_unlock(&fsdb->fsdb_mutex);
5654 name_destroy(&logname);
5655 /* request for update */
5656 mgs_revoke_lock(mgs, fsdb, CONFIG_T_CONFIG);
5662 mutex_unlock(&fsdb->fsdb_mutex);
5666 if (canceled_label != NULL)
5667 OBD_FREE(canceled_label, label_sz);
5669 OBD_FREE(label, label_sz);
5672 mgs_unlink_fsdb(mgs, fsdb);
5673 mgs_put_fsdb(mgs, fsdb);