X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;ds=sidebyside;f=lustre%2Fmgs%2Fmgs_llog.c;h=400a3ce33a7d7b9700a8c6b4472ec18c93e7810b;hb=f7815c80d95b20c97317fbd7010013dca009121e;hp=70a83dc10f6ecf1a03ff20e2a7d1732b1be7e708;hpb=25420c75e45a91c6131d52a674869d6d30ab36bf;p=fs%2Flustre-release.git diff --git a/lustre/mgs/mgs_llog.c b/lustre/mgs/mgs_llog.c index 70a83dc..400a3ce 100644 --- a/lustre/mgs/mgs_llog.c +++ b/lustre/mgs/mgs_llog.c @@ -15,11 +15,7 @@ * * You should have received a copy of the GNU General Public License * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * http://www.gnu.org/licenses/gpl-2.0.html * * GPL HEADER END */ @@ -27,7 +23,7 @@ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2011, 2015, Intel Corporation. + * Copyright (c) 2011, 2016, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -55,16 +51,25 @@ /********************** Class functions ********************/ -/* Find all logs in CONFIG directory and link then into list */ -int class_dentry_readdir(const struct lu_env *env, - struct mgs_device *mgs, struct list_head *log_list) +/** + * Find all logs in CONFIG directory and link then into list. + * + * \param[in] env pointer to the thread context + * \param[in] mgs pointer to the mgs device + * \param[out] log_list the list to hold the found llog name entry + * + * \retval 0 for success + * \retval negative error number on failure + **/ +int class_dentry_readdir(const struct lu_env *env, struct mgs_device *mgs, + struct list_head *log_list) { - struct dt_object *dir = mgs->mgs_configs_dir; + struct dt_object *dir = mgs->mgs_configs_dir; const struct dt_it_ops *iops; - struct dt_it *it; + struct dt_it *it; struct mgs_direntry *de; - char *key; - int rc, key_sz; + char *key; + int rc, key_sz; INIT_LIST_HEAD(log_list); @@ -100,6 +105,15 @@ int class_dentry_readdir(const struct lu_env *env, goto next; } + /* filter out ".bak" files */ + /* sizeof(".bak") - 1 == 3 */ + if (key_sz >= 3 && + !memcmp(".bak", key + key_sz - 3, 3)) { + CDEBUG(D_MGS, "Skipping backup file %.*s\n", + key_sz, key); + goto next; + } + de = mgs_direntry_alloc(key_sz + 1); if (de == NULL) { rc = -ENOMEM; @@ -114,15 +128,25 @@ int class_dentry_readdir(const struct lu_env *env, next: rc = iops->next(env, it); } while (rc == 0); - rc = 0; + if (rc > 0) + rc = 0; iops->put(env, it); fini: iops->fini(env, it); - if (rc) + if (rc) { + struct mgs_direntry *n; + CERROR("%s: key failed when listing %s: rc = %d\n", mgs->mgs_obd->obd_name, MOUNT_CONFIGS_DIR, rc); + + list_for_each_entry_safe(de, n, log_list, mde_list) { + list_del_init(&de->mde_list); + mgs_direntry_free(de); + } + } + RETURN(rc); } @@ -211,9 +235,11 @@ static int mgs_fsdb_handler(const struct lu_env *env, struct llog_handle *llh, } rc = 0; CDEBUG(D_MGS, "MDT index is %u\n", index); - set_bit(index, fsdb->fsdb_mdt_index_map); - fsdb->fsdb_mdt_count ++; - } + if (!test_bit(index, fsdb->fsdb_mdt_index_map)) { + set_bit(index, fsdb->fsdb_mdt_index_map); + fsdb->fsdb_mdt_count++; + } + } /** * figure out the old config. fsdb_gen = 0 means old log @@ -255,10 +281,12 @@ static int mgs_get_fsdb_from_llog(const struct lu_env *env, struct mgs_device *mgs, struct fs_db *fsdb) { - char *logname; - struct llog_handle *loghandle; - struct llog_ctxt *ctxt; - struct mgs_fsdb_handler_data d = { fsdb, 0 }; + char *logname; + struct llog_handle *loghandle; + struct llog_ctxt *ctxt; + struct mgs_fsdb_handler_data d = { + .fsdb = fsdb, + }; int rc; ENTRY; @@ -311,98 +339,185 @@ static void mgs_free_fsdb_srpc(struct fs_db *fsdb) sptlrpc_rule_set_free(&fsdb->fsdb_srpc_gen); } -struct fs_db *mgs_find_fsdb(struct mgs_device *mgs, char *fsname) +static void mgs_unlink_fsdb(struct mgs_device *mgs, struct fs_db *fsdb) { - struct fs_db *fsdb; + mutex_lock(&mgs->mgs_mutex); + if (likely(!list_empty(&fsdb->fsdb_list))) { + LASSERTF(atomic_read(&fsdb->fsdb_ref) >= 2, + "Invalid ref %d on %s\n", + atomic_read(&fsdb->fsdb_ref), + fsdb->fsdb_name); + + list_del_init(&fsdb->fsdb_list); + /* Drop the reference on the list.*/ + mgs_put_fsdb(mgs, fsdb); + } + mutex_unlock(&mgs->mgs_mutex); +} + +/* The caller must hold mgs->mgs_mutex. */ +static inline struct fs_db * +mgs_find_fsdb_noref(struct mgs_device *mgs, const char *fsname) +{ + struct fs_db *fsdb; struct list_head *tmp; list_for_each(tmp, &mgs->mgs_fs_db_list) { fsdb = list_entry(tmp, struct fs_db, fsdb_list); - if (strcmp(fsdb->fsdb_name, fsname) == 0) - return fsdb; - } - return NULL; + if (strcmp(fsdb->fsdb_name, fsname) == 0) + return fsdb; + } + + return NULL; } -/* caller must hold the mgs->mgs_fs_db_lock */ +/* The caller must hold mgs->mgs_mutex. */ +static void mgs_remove_fsdb_by_name(struct mgs_device *mgs, const char *name) +{ + struct fs_db *fsdb; + + fsdb = mgs_find_fsdb_noref(mgs, name); + if (fsdb) { + list_del_init(&fsdb->fsdb_list); + /* Drop the reference on the list.*/ + mgs_put_fsdb(mgs, fsdb); + } +} + +/* The caller must hold mgs->mgs_mutex. */ +struct fs_db *mgs_find_fsdb(struct mgs_device *mgs, const char *fsname) +{ + struct fs_db *fsdb; + + fsdb = mgs_find_fsdb_noref(mgs, fsname); + if (fsdb) + atomic_inc(&fsdb->fsdb_ref); + + return fsdb; +} + +/* The caller must hold mgs->mgs_mutex. */ static struct fs_db *mgs_new_fsdb(const struct lu_env *env, struct mgs_device *mgs, char *fsname) { - struct fs_db *fsdb; - int rc; - ENTRY; + struct fs_db *fsdb; + int rc; + ENTRY; + + if (strlen(fsname) >= sizeof(fsdb->fsdb_name)) { + CERROR("fsname %s is too long\n", fsname); - if (strlen(fsname) >= sizeof(fsdb->fsdb_name)) { - CERROR("fsname %s is too long\n", fsname); RETURN(ERR_PTR(-EINVAL)); - } + } - OBD_ALLOC_PTR(fsdb); - if (!fsdb) + OBD_ALLOC_PTR(fsdb); + if (!fsdb) RETURN(ERR_PTR(-ENOMEM)); - strcpy(fsdb->fsdb_name, fsname); + strncpy(fsdb->fsdb_name, fsname, sizeof(fsdb->fsdb_name)); mutex_init(&fsdb->fsdb_mutex); + INIT_LIST_HEAD(&fsdb->fsdb_list); set_bit(FSDB_UDESC, &fsdb->fsdb_flags); fsdb->fsdb_gen = 1; + INIT_LIST_HEAD(&fsdb->fsdb_clients); + atomic_set(&fsdb->fsdb_notify_phase, 0); + init_waitqueue_head(&fsdb->fsdb_notify_waitq); + init_completion(&fsdb->fsdb_notify_comp); - if (strcmp(fsname, MGSSELF_NAME) == 0) { + if (strcmp(fsname, MGSSELF_NAME) == 0) { set_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags); fsdb->fsdb_mgs = mgs; - } else { - OBD_ALLOC(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE); - OBD_ALLOC(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE); - if (!fsdb->fsdb_ost_index_map || !fsdb->fsdb_mdt_index_map) { - CERROR("No memory for index maps\n"); + if (logname_is_barrier(fsname)) + goto add; + } else { + OBD_ALLOC(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE); + if (!fsdb->fsdb_mdt_index_map) { + CERROR("No memory for MDT index maps\n"); + GOTO(err, rc = -ENOMEM); - } + } - rc = name_create(&fsdb->fsdb_clilov, fsname, "-clilov"); - if (rc) - GOTO(err, rc); - rc = name_create(&fsdb->fsdb_clilmv, fsname, "-clilmv"); - if (rc) - GOTO(err, rc); + OBD_ALLOC(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE); + if (!fsdb->fsdb_ost_index_map) { + CERROR("No memory for OST index maps\n"); - /* initialise data for NID table */ - mgs_ir_init_fs(env, mgs, fsdb); + GOTO(err, rc = -ENOMEM); + } + + if (logname_is_barrier(fsname)) + goto add; + rc = name_create(&fsdb->fsdb_clilov, fsname, "-clilov"); + if (rc) + GOTO(err, rc); + + rc = name_create(&fsdb->fsdb_clilmv, fsname, "-clilmv"); + if (rc) + GOTO(err, rc); + + /* initialise data for NID table */ + mgs_ir_init_fs(env, mgs, fsdb); lproc_mgs_add_live(mgs, fsdb); - } + } + + if (!test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags) && + strcmp(PARAMS_FILENAME, fsname) != 0) { + /* populate the db from the client llog */ + rc = mgs_get_fsdb_from_llog(env, mgs, fsdb); + if (rc) { + CERROR("Can't get db from client log %d\n", rc); + + GOTO(err, rc); + } + } + + /* populate srpc rules from params llog */ + rc = mgs_get_fsdb_srpc_from_llog(env, mgs, fsdb); + if (rc) { + CERROR("Can't get db from params log %d\n", rc); + GOTO(err, rc); + } + +add: + /* One ref is for the fsdb on the list. + * The other ref is for the caller. */ + atomic_set(&fsdb->fsdb_ref, 2); list_add(&fsdb->fsdb_list, &mgs->mgs_fs_db_list); - RETURN(fsdb); + RETURN(fsdb); + err: - if (fsdb->fsdb_ost_index_map) - OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE); - if (fsdb->fsdb_mdt_index_map) - OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE); - name_destroy(&fsdb->fsdb_clilov); - name_destroy(&fsdb->fsdb_clilmv); - OBD_FREE_PTR(fsdb); + atomic_set(&fsdb->fsdb_ref, 1); + mgs_put_fsdb(mgs, fsdb); + RETURN(ERR_PTR(rc)); } static void mgs_free_fsdb(struct mgs_device *mgs, struct fs_db *fsdb) { - /* wait for anyone with the sem */ - mutex_lock(&fsdb->fsdb_mutex); + LASSERT(list_empty(&fsdb->fsdb_list)); + lproc_mgs_del_live(mgs, fsdb); - list_del(&fsdb->fsdb_list); - - /* deinitialize fsr */ - mgs_ir_fini_fs(mgs, fsdb); - - if (fsdb->fsdb_ost_index_map) - OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE); - if (fsdb->fsdb_mdt_index_map) - OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE); - name_destroy(&fsdb->fsdb_clilov); - name_destroy(&fsdb->fsdb_clilmv); - mgs_free_fsdb_srpc(fsdb); - mutex_unlock(&fsdb->fsdb_mutex); - OBD_FREE_PTR(fsdb); + + /* deinitialize fsr */ + if (fsdb->fsdb_mgs) + mgs_ir_fini_fs(mgs, fsdb); + + if (fsdb->fsdb_ost_index_map) + OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE); + if (fsdb->fsdb_mdt_index_map) + OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE); + name_destroy(&fsdb->fsdb_clilov); + name_destroy(&fsdb->fsdb_clilmv); + mgs_free_fsdb_srpc(fsdb); + OBD_FREE_PTR(fsdb); +} + +void mgs_put_fsdb(struct mgs_device *mgs, struct fs_db *fsdb) +{ + if (atomic_dec_and_test(&fsdb->fsdb_ref)) + mgs_free_fsdb(mgs, fsdb); } int mgs_init_fsdb_list(struct mgs_device *mgs) @@ -419,62 +534,35 @@ int mgs_cleanup_fsdb_list(struct mgs_device *mgs) mutex_lock(&mgs->mgs_mutex); list_for_each_safe(tmp, tmp2, &mgs->mgs_fs_db_list) { fsdb = list_entry(tmp, struct fs_db, fsdb_list); - mgs_free_fsdb(mgs, fsdb); + list_del_init(&fsdb->fsdb_list); + mgs_put_fsdb(mgs, fsdb); } mutex_unlock(&mgs->mgs_mutex); return 0; } -int mgs_find_or_make_fsdb(const struct lu_env *env, - struct mgs_device *mgs, char *name, - struct fs_db **dbh) +int mgs_find_or_make_fsdb(const struct lu_env *env, struct mgs_device *mgs, + char *name, struct fs_db **dbh) { - struct fs_db *fsdb; - int rc = 0; - + struct fs_db *fsdb; + int rc = 0; ENTRY; + mutex_lock(&mgs->mgs_mutex); fsdb = mgs_find_fsdb(mgs, name); - if (fsdb) { - mutex_unlock(&mgs->mgs_mutex); - *dbh = fsdb; - RETURN(0); - } + if (!fsdb) { + fsdb = mgs_new_fsdb(env, mgs, name); + if (IS_ERR(fsdb)) + rc = PTR_ERR(fsdb); - CDEBUG(D_MGS, "Creating new db\n"); - fsdb = mgs_new_fsdb(env, mgs, name); - /* lock fsdb_mutex until the db is loaded from llogs */ - if (!IS_ERR(fsdb)) - mutex_lock(&fsdb->fsdb_mutex); + CDEBUG(D_MGS, "Created new db: rc = %d\n", rc); + } mutex_unlock(&mgs->mgs_mutex); - if (IS_ERR(fsdb)) - RETURN(PTR_ERR(fsdb)); - - if (!test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) { - /* populate the db from the client llog */ - rc = mgs_get_fsdb_from_llog(env, mgs, fsdb); - if (rc) { - CERROR("Can't get db from client log %d\n", rc); - GOTO(out_free, rc); - } - } - - /* populate srpc rules from params llog */ - rc = mgs_get_fsdb_srpc_from_llog(env, mgs, fsdb); - if (rc) { - CERROR("Can't get db from params log %d\n", rc); - GOTO(out_free, rc); - } - - mutex_unlock(&fsdb->fsdb_mutex); - *dbh = fsdb; - RETURN(0); + if (!rc) + *dbh = fsdb; -out_free: - mutex_unlock(&fsdb->fsdb_mutex); - mgs_free_fsdb(mgs, fsdb); - return rc; + RETURN(rc); } /* 1 = index in use @@ -498,18 +586,23 @@ int mgs_check_index(const struct lu_env *env, } if (test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) - RETURN(-1); + GOTO(out, rc = -1); - if (mti->mti_flags & LDD_F_SV_TYPE_OST) - imap = fsdb->fsdb_ost_index_map; - else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) - imap = fsdb->fsdb_mdt_index_map; - else - RETURN(-EINVAL); + if (mti->mti_flags & LDD_F_SV_TYPE_OST) + imap = fsdb->fsdb_ost_index_map; + else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) + imap = fsdb->fsdb_mdt_index_map; + else + GOTO(out, rc = -EINVAL); if (test_bit(mti->mti_stripe_index, imap)) - RETURN(1); - RETURN(0); + GOTO(out, rc = 1); + + GOTO(out, rc = 0); + +out: + mgs_put_fsdb(mgs, fsdb); + return rc; } static __inline__ int next_index(void *index_map, int map_len) @@ -523,6 +616,28 @@ static __inline__ int next_index(void *index_map, int map_len) return -1; } +/* Make the mdt/ost server obd name based on the filesystem name */ +static bool server_make_name(u32 flags, u16 index, const char *fs, + char *name_buf, size_t name_buf_size) +{ + bool invalid_flag = false; + + if (flags & (LDD_F_SV_TYPE_MDT | LDD_F_SV_TYPE_OST)) { + if (!(flags & LDD_F_SV_ALL)) + snprintf(name_buf, name_buf_size, "%.8s%c%s%04x", fs, + (flags & LDD_F_VIRGIN) ? ':' : + ((flags & LDD_F_WRITECONF) ? '=' : '-'), + (flags & LDD_F_SV_TYPE_MDT) ? "MDT" : "OST", + index); + } else if (flags & LDD_F_SV_TYPE_MGS) { + snprintf(name_buf, name_buf_size, "MGS"); + } else { + CERROR("unknown server type %#x\n", flags); + invalid_flag = true; + } + return invalid_flag; +} + /* Return codes: 0 newly marked as in use <0 err @@ -556,8 +671,6 @@ static int mgs_set_index(const struct lu_env *env, if (rc == -1) GOTO(out_up, rc = -ERANGE); mti->mti_stripe_index = rc; - if (mti->mti_flags & LDD_F_SV_TYPE_MDT) - fsdb->fsdb_mdt_count ++; } /* the last index(0xffff) is reserved for default value. */ @@ -582,21 +695,30 @@ static int mgs_set_index(const struct lu_env *env, CDEBUG(D_MGS, "Server %s updating index %d\n", mti->mti_svname, mti->mti_stripe_index); GOTO(out_up, rc = EALREADY); - } - } + } + } else { + set_bit(mti->mti_stripe_index, imap); + if (mti->mti_flags & LDD_F_SV_TYPE_MDT) + fsdb->fsdb_mdt_count++; + } set_bit(mti->mti_stripe_index, imap); clear_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags); - mutex_unlock(&fsdb->fsdb_mutex); - server_make_name(mti->mti_flags & ~(LDD_F_VIRGIN | LDD_F_WRITECONF), - mti->mti_stripe_index, mti->mti_fsname, mti->mti_svname); + if (server_make_name(mti->mti_flags & ~(LDD_F_VIRGIN | LDD_F_WRITECONF), + mti->mti_stripe_index, mti->mti_fsname, + mti->mti_svname, sizeof(mti->mti_svname))) { + CERROR("unknown server type %#x\n", mti->mti_flags); + GOTO(out_up, rc = -EINVAL); + } - CDEBUG(D_MGS, "Set index for %s to %d\n", mti->mti_svname, - mti->mti_stripe_index); + CDEBUG(D_MGS, "Set index for %s to %d\n", mti->mti_svname, + mti->mti_stripe_index); + + GOTO(out_up, rc = 0); - RETURN(0); out_up: mutex_unlock(&fsdb->fsdb_mutex); + mgs_put_fsdb(mgs, fsdb); return rc; } @@ -605,6 +727,116 @@ struct mgs_modify_lookup { int mml_modified; }; +static int mgs_check_record_match(const struct lu_env *env, + struct llog_handle *llh, + struct llog_rec_hdr *rec, void *data) +{ + struct cfg_marker *mc_marker = data; + struct cfg_marker *marker; + struct lustre_cfg *lcfg = REC_DATA(rec); + int cfg_len = REC_DATA_LEN(rec); + int rc; + ENTRY; + + + if (rec->lrh_type != OBD_CFG_REC) { + CDEBUG(D_ERROR, "Unhandled lrh_type: %#x\n", rec->lrh_type); + RETURN(-EINVAL); + } + + rc = lustre_cfg_sanity_check(lcfg, cfg_len); + if (rc) { + CDEBUG(D_ERROR, "Insane cfg\n"); + RETURN(rc); + } + + /* We only care about markers */ + if (lcfg->lcfg_command != LCFG_MARKER) + RETURN(0); + + marker = lustre_cfg_buf(lcfg, 1); + + if (marker->cm_flags & CM_SKIP) + RETURN(0); + + if ((strcmp(mc_marker->cm_comment, marker->cm_comment) == 0) && + (strcmp(mc_marker->cm_tgtname, marker->cm_tgtname) == 0)) { + /* Found a non-skipped marker match */ + CDEBUG(D_MGS, "Matched rec %u marker %d flag %x %s %s\n", + rec->lrh_index, marker->cm_step, + marker->cm_flags, marker->cm_tgtname, + marker->cm_comment); + rc = LLOG_PROC_BREAK; + } + + RETURN(rc); +} + +/** + * Check an existing config log record with matching comment and device + * Return code: + * 0 - checked successfully, + * LLOG_PROC_BREAK - record matches + * negative - error + */ +static int mgs_check_marker(const struct lu_env *env, struct mgs_device *mgs, + struct fs_db *fsdb, struct mgs_target_info *mti, + char *logname, char *devname, char *comment) +{ + struct llog_handle *loghandle; + struct llog_ctxt *ctxt; + struct cfg_marker *mc_marker; + int rc; + + ENTRY; + + LASSERT(mutex_is_locked(&fsdb->fsdb_mutex)); + CDEBUG(D_MGS, "mgs check %s/%s/%s\n", logname, devname, comment); + + ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT); + LASSERT(ctxt != NULL); + rc = llog_open(env, ctxt, &loghandle, NULL, logname, LLOG_OPEN_EXISTS); + if (rc < 0) { + if (rc == -ENOENT) + rc = 0; + GOTO(out_pop, rc); + } + + rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL); + if (rc) + GOTO(out_close, rc); + + if (llog_get_size(loghandle) <= 1) + GOTO(out_close, rc = 0); + + OBD_ALLOC_PTR(mc_marker); + if (!mc_marker) + GOTO(out_close, rc = -ENOMEM); + if (strlcpy(mc_marker->cm_comment, comment, + sizeof(mc_marker->cm_comment)) >= + sizeof(mc_marker->cm_comment)) + GOTO(out_free, rc = -E2BIG); + if (strlcpy(mc_marker->cm_tgtname, devname, + sizeof(mc_marker->cm_tgtname)) >= + sizeof(mc_marker->cm_tgtname)) + GOTO(out_free, rc = -E2BIG); + + rc = llog_process(env, loghandle, mgs_check_record_match, + (void *)mc_marker, NULL); + +out_free: + OBD_FREE_PTR(mc_marker); + +out_close: + llog_close(env, loghandle); +out_pop: + if (rc && rc != LLOG_PROC_BREAK) + CDEBUG(D_ERROR, "%s: mgs check %s/%s failed: rc = %d\n", + mgs->mgs_obd->obd_name, mti->mti_svname, comment, rc); + llog_ctxt_put(ctxt); + RETURN(rc); +} + static int mgs_modify_handler(const struct lu_env *env, struct llog_handle *llh, struct llog_rec_hdr *rec, void *data) @@ -1211,7 +1443,7 @@ int mgs_replace_nids(const struct lu_env *env, int rc; __u32 index; char *logname; - struct fs_db *fsdb; + struct fs_db *fsdb = NULL; unsigned int i; int conn_state; struct obd_device *mgs_obd = mgs->mgs_obd; @@ -1266,6 +1498,9 @@ out: mgs_obd->obd_no_conn = conn_state; spin_unlock(&mgs_obd->obd_dev_lock); + if (fsdb) + mgs_put_fsdb(mgs, fsdb); + RETURN(rc); } @@ -2293,34 +2528,34 @@ static int mgs_write_log_mdt(const struct lu_env *env, #14 L mount_option 0: 1:client 2:lov1 3:MDC_uml1_mdsA_MNT_client */ - /* copy client info about lov/lmv */ - mgi->mgi_comp.comp_mti = mti; - mgi->mgi_comp.comp_fsdb = fsdb; + /* copy client info about lov/lmv */ + mgi->mgi_comp.comp_mti = mti; + mgi->mgi_comp.comp_fsdb = fsdb; - rc = mgs_steal_llog_for_mdt_from_client(env, mgs, cliname, - &mgi->mgi_comp); - if (rc) - GOTO(out_free, rc); - rc = mgs_write_log_mdc_to_lmv(env, mgs, fsdb, mti, cliname, - fsdb->fsdb_clilmv); - if (rc) - GOTO(out_free, rc); + rc = mgs_steal_llog_for_mdt_from_client(env, mgs, cliname, + &mgi->mgi_comp); + if (rc) + GOTO(out_free, rc); + rc = mgs_write_log_mdc_to_lmv(env, mgs, fsdb, mti, cliname, + fsdb->fsdb_clilmv); + if (rc) + GOTO(out_free, rc); - /* add mountopts */ - rc = record_start_log(env, mgs, &llh, cliname); - if (rc) - GOTO(out_free, rc); + /* add mountopts */ + rc = record_start_log(env, mgs, &llh, cliname); + if (rc) + GOTO(out_free, rc); - rc = record_marker(env, llh, fsdb, CM_START, cliname, - "mount opts"); - if (rc) - GOTO(out_end, rc); - rc = record_mount_opt(env, llh, cliname, fsdb->fsdb_clilov, - fsdb->fsdb_clilmv); - if (rc) - GOTO(out_end, rc); - rc = record_marker(env, llh, fsdb, CM_END, cliname, - "mount opts"); + rc = record_marker(env, llh, fsdb, CM_START, cliname, + "mount opts"); + if (rc) + GOTO(out_end, rc); + rc = record_mount_opt(env, llh, cliname, fsdb->fsdb_clilov, + fsdb->fsdb_clilmv); + if (rc) + GOTO(out_end, rc); + rc = record_marker(env, llh, fsdb, CM_END, cliname, + "mount opts"); if (rc) GOTO(out_end, rc); @@ -2335,8 +2570,34 @@ static int mgs_write_log_mdt(const struct lu_env *env, if (rc) GOTO(out_end, rc); - rc = mgs_write_log_osp_to_mdt(env, mgs, fsdb, mti, - i, logname); + /* NB: If the log for the MDT is empty, it means + * the MDT is only added to the index + * map, and not being process yet, i.e. this + * is an unregistered MDT, see mgs_write_log_target(). + * so we should skip it. Otherwise + * + * 1. MGS get register request for MDT1 and MDT2. + * + * 2. Then both MDT1 and MDT2 are added into + * fsdb_mdt_index_map. (see mgs_set_index()). + * + * 3. Then MDT1 get the lock of fsdb_mutex, then + * generate the config log, here, it will regard MDT2 + * as an existent MDT, and generate "add osp" for + * lustre-MDT0001-osp-MDT0002. Note: at the moment + * MDT0002 config log is still empty, so it will + * add "add osp" even before "lov setup", which + * will definitly cause trouble. + * + * 4. MDT1 registeration finished, fsdb_mutex is + * released, then MDT2 get in, then in above + * mgs_steal_llog_for_mdt_from_client(), it will + * add another osp log for lustre-MDT0001-osp-MDT0002, + * which will cause another trouble.*/ + if (!mgs_log_is_empty(env, mgs, logname)) + rc = mgs_write_log_osp_to_mdt(env, mgs, fsdb, + mti, i, logname); + name_destroy(&logname); if (rc) GOTO(out_end, rc); @@ -2867,6 +3128,7 @@ static int mgs_write_log_quota(const struct lu_env *env, struct mgs_device *mgs, CDEBUG(D_MGS, "global '%s'\n", quota); if (strchr(tmp, 'u') == NULL && strchr(tmp, 'g') == NULL && + strchr(tmp, 'p') == NULL && strcmp(tmp, "none") != 0) { CERROR("enable option(%s) isn't supported\n", tmp); return -EINVAL; @@ -3262,7 +3524,7 @@ static int mgs_write_log_param(const struct lu_env *env, struct mgs_thread_info *mgi = mgs_env_info(env); char *logname; char *tmp; - int rc = 0, rc2 = 0; + int rc = 0; ENTRY; /* For various parameter settings, we have to figure out which logs @@ -3337,7 +3599,7 @@ static int mgs_write_log_param(const struct lu_env *env, LCONSOLE_ERROR_MSG(0x144, "%s: MDC0 can not be" " (de)activated.\n", mti->mti_svname); - GOTO(end, rc = -EINVAL); + GOTO(end, rc = -EPERM); } } @@ -3677,56 +3939,21 @@ active_err: } LCONSOLE_WARN("Ignoring unrecognized param '%s'\n", ptr); - rc2 = -ENOSYS; end: if (rc) CERROR("err %d on param '%s'\n", rc, ptr); - RETURN(rc ?: rc2); + RETURN(rc); } -/* Not implementing automatic failover nid addition at this time. */ -int mgs_check_failnid(const struct lu_env *env, struct mgs_device *mgs, - struct mgs_target_info *mti) +int mgs_write_log_target(const struct lu_env *env, struct mgs_device *mgs, + struct mgs_target_info *mti, struct fs_db *fsdb) { -#if 0 - struct fs_db *fsdb; - int rc; - ENTRY; - - rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb); - if (rc) - RETURN(rc); - - if (mgs_log_is_empty(obd, mti->mti_svname)) - /* should never happen */ - RETURN(-ENOENT); - - CDEBUG(D_MGS, "Checking for new failnids for %s\n", mti->mti_svname); + char *buf, *params; + int rc = -EINVAL; - /* FIXME We can just check mti->params to see if we're already in - the failover list. Modify mti->params for rewriting back at - server_register_target(). */ - - mutex_lock(&fsdb->fsdb_mutex); - rc = mgs_write_log_add_failnid(obd, fsdb, mti); - mutex_unlock(&fsdb->fsdb_mutex); - char *buf, *params; - int rc = -EINVAL; - - RETURN(rc); -#endif - return 0; -} - -int mgs_write_log_target(const struct lu_env *env, struct mgs_device *mgs, - struct mgs_target_info *mti, struct fs_db *fsdb) -{ - char *buf, *params; - int rc = -EINVAL; - - ENTRY; + ENTRY; /* set/check the new target index */ rc = mgs_set_index(env, mgs, mti); @@ -3745,6 +3972,9 @@ int mgs_write_log_target(const struct lu_env *env, struct mgs_device *mgs, rc = 0; } + OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_WRITE_TARGET_DELAY, cfs_fail_val > 0 ? + cfs_fail_val : 10); + mutex_lock(&fsdb->fsdb_mutex); if (mti->mti_flags & @@ -3824,27 +4054,37 @@ int mgs_erase_log(const struct lu_env *env, struct mgs_device *mgs, char *name) } /* erase all logs for the given fs */ -int mgs_erase_logs(const struct lu_env *env, struct mgs_device *mgs, char *fsname) +int mgs_erase_logs(const struct lu_env *env, struct mgs_device *mgs, + const char *fsname) { - struct fs_db *fsdb; struct list_head log_list; struct mgs_direntry *dirent, *n; - int rc, len = strlen(fsname); + char barrier_name[20] = {}; char *suffix; + int count = 0; + int rc, len = strlen(fsname); ENTRY; + mutex_lock(&mgs->mgs_mutex); + /* Find all the logs in the CONFIGS directory */ rc = class_dentry_readdir(env, mgs, &log_list); - if (rc) + if (rc) { + mutex_unlock(&mgs->mgs_mutex); RETURN(rc); + } - mutex_lock(&mgs->mgs_mutex); - - /* Delete the fs db */ - fsdb = mgs_find_fsdb(mgs, fsname); - if (fsdb) - mgs_free_fsdb(mgs, fsdb); + if (list_empty(&log_list)) { + mutex_unlock(&mgs->mgs_mutex); + RETURN(-ENOENT); + } + snprintf(barrier_name, sizeof(barrier_name) - 1, "%s-%s", + fsname, BARRIER_FILENAME); + /* Delete the barrier fsdb */ + mgs_remove_fsdb_by_name(mgs, barrier_name); + /* Delete the fs db */ + mgs_remove_fsdb_by_name(mgs, fsname); mutex_unlock(&mgs->mgs_mutex); list_for_each_entry_safe(dirent, n, &log_list, mde_list) { @@ -3856,12 +4096,16 @@ int mgs_erase_logs(const struct lu_env *env, struct mgs_device *mgs, char *fsnam CDEBUG(D_MGS, "Removing log %s\n", dirent->mde_name); mgs_erase_log(env, mgs, dirent->mde_name); + count++; } } mgs_direntry_free(dirent); } - RETURN(rc); + if (count == 0) + rc = -ENOENT; + + RETURN(rc); } /* list all logs for the given fs */ @@ -3886,7 +4130,7 @@ int mgs_list_logs(const struct lu_env *env, struct mgs_device *mgs, list_del_init(&dirent->mde_list); suffix = strrchr(dirent->mde_name, '-'); if (suffix != NULL) { - l = snprintf(out, remains, "config log: $%s\n", + l = snprintf(out, remains, "config_log: %s\n", dirent->mde_name); out += l; remains -= l; @@ -3898,6 +4142,546 @@ int mgs_list_logs(const struct lu_env *env, struct mgs_device *mgs, RETURN(rc); } +struct mgs_lcfg_fork_data { + struct lustre_cfg_bufs mlfd_bufs; + struct mgs_device *mlfd_mgs; + struct llog_handle *mlfd_llh; + const char *mlfd_oldname; + const char *mlfd_newname; + char mlfd_data[0]; +}; + +static bool contain_valid_fsname(char *buf, const char *fsname, + int buflen, int namelen) +{ + if (buflen < namelen) + return false; + + if (memcmp(buf, fsname, namelen) != 0) + return false; + + if (buf[namelen] != '\0' && buf[namelen] != '-') + return false; + + return true; +} + +static int mgs_lcfg_fork_handler(const struct lu_env *env, + struct llog_handle *o_llh, + struct llog_rec_hdr *o_rec, void *data) +{ + struct mgs_lcfg_fork_data *mlfd = data; + struct lustre_cfg_bufs *n_bufs = &mlfd->mlfd_bufs; + struct lustre_cfg *o_lcfg = (struct lustre_cfg *)(o_rec + 1); + struct llog_cfg_rec *lcr; + char *o_buf; + char *n_buf = mlfd->mlfd_data; + int o_buflen; + int o_namelen = strlen(mlfd->mlfd_oldname); + int n_namelen = strlen(mlfd->mlfd_newname); + int diff = n_namelen - o_namelen; + __u32 cmd = o_lcfg->lcfg_command; + __u32 cnt = o_lcfg->lcfg_bufcount; + int rc; + int i; + ENTRY; + + /* buf[0] */ + o_buf = lustre_cfg_buf(o_lcfg, 0); + o_buflen = o_lcfg->lcfg_buflens[0]; + if (contain_valid_fsname(o_buf, mlfd->mlfd_oldname, o_buflen, + o_namelen)) { + memcpy(n_buf, mlfd->mlfd_newname, n_namelen); + memcpy(n_buf + n_namelen, o_buf + o_namelen, + o_buflen - o_namelen); + lustre_cfg_bufs_reset(n_bufs, n_buf); + n_buf += cfs_size_round(o_buflen + diff); + } else { + lustre_cfg_bufs_reset(n_bufs, o_buflen != 0 ? o_buf : NULL); + } + + switch (cmd) { + case LCFG_MARKER: { + struct cfg_marker *o_marker; + struct cfg_marker *n_marker; + int tgt_namelen; + + if (cnt != 2) { + CDEBUG(D_MGS, "Unknown cfg marker entry with %d " + "buffers\n", cnt); + RETURN(-EINVAL); + } + + /* buf[1] is marker */ + o_buf = lustre_cfg_buf(o_lcfg, 1); + o_buflen = o_lcfg->lcfg_buflens[1]; + o_marker = (struct cfg_marker *)o_buf; + if (!contain_valid_fsname(o_marker->cm_tgtname, + mlfd->mlfd_oldname, + sizeof(o_marker->cm_tgtname), + o_namelen)) { + lustre_cfg_bufs_set(n_bufs, 1, o_marker, + sizeof(*o_marker)); + break; + } + + n_marker = (struct cfg_marker *)n_buf; + *n_marker = *o_marker; + memcpy(n_marker->cm_tgtname, mlfd->mlfd_newname, n_namelen); + tgt_namelen = strlen(o_marker->cm_tgtname); + if (tgt_namelen > o_namelen) + memcpy(n_marker->cm_tgtname + n_namelen, + o_marker->cm_tgtname + o_namelen, + tgt_namelen - o_namelen); + n_marker->cm_tgtname[tgt_namelen + diff] = '\0'; + lustre_cfg_bufs_set(n_bufs, 1, n_marker, sizeof(*n_marker)); + break; + } + case LCFG_PARAM: + case LCFG_SET_PARAM: { + for (i = 1; i < cnt; i++) + /* buf[i] is the param value, reuse it directly */ + lustre_cfg_bufs_set(n_bufs, i, + lustre_cfg_buf(o_lcfg, i), + o_lcfg->lcfg_buflens[i]); + break; + } + case LCFG_POOL_NEW: + case LCFG_POOL_ADD: + case LCFG_POOL_REM: + case LCFG_POOL_DEL: { + if (cnt < 3 || cnt > 4) { + CDEBUG(D_MGS, "Unknown cfg pool (%x) entry with %d " + "buffers\n", cmd, cnt); + RETURN(-EINVAL); + } + + /* buf[1] is fsname */ + o_buf = lustre_cfg_buf(o_lcfg, 1); + o_buflen = o_lcfg->lcfg_buflens[1]; + memcpy(n_buf, mlfd->mlfd_newname, n_namelen); + memcpy(n_buf + n_namelen, o_buf + o_namelen, + o_buflen - o_namelen); + lustre_cfg_bufs_set(n_bufs, 1, n_buf, o_buflen + diff); + n_buf += cfs_size_round(o_buflen + diff); + + /* buf[2] is the pool name, reuse it directly */ + lustre_cfg_bufs_set(n_bufs, 2, lustre_cfg_buf(o_lcfg, 2), + o_lcfg->lcfg_buflens[2]); + + if (cnt == 3) + break; + + /* buf[3] is ostname */ + o_buf = lustre_cfg_buf(o_lcfg, 3); + o_buflen = o_lcfg->lcfg_buflens[3]; + memcpy(n_buf, mlfd->mlfd_newname, n_namelen); + memcpy(n_buf + n_namelen, o_buf + o_namelen, + o_buflen - o_namelen); + lustre_cfg_bufs_set(n_bufs, 3, n_buf, o_buflen + diff); + break; + } + case LCFG_SETUP: { + if (cnt == 2) { + o_buflen = o_lcfg->lcfg_buflens[1]; + if (o_buflen == sizeof(struct lov_desc) || + o_buflen == sizeof(struct lmv_desc)) { + char *o_uuid; + char *n_uuid; + int uuid_len; + + /* buf[1] */ + o_buf = lustre_cfg_buf(o_lcfg, 1); + if (o_buflen == sizeof(struct lov_desc)) { + struct lov_desc *o_desc = + (struct lov_desc *)o_buf; + struct lov_desc *n_desc = + (struct lov_desc *)n_buf; + + *n_desc = *o_desc; + o_uuid = o_desc->ld_uuid.uuid; + n_uuid = n_desc->ld_uuid.uuid; + uuid_len = sizeof(o_desc->ld_uuid.uuid); + } else { + struct lmv_desc *o_desc = + (struct lmv_desc *)o_buf; + struct lmv_desc *n_desc = + (struct lmv_desc *)n_buf; + + *n_desc = *o_desc; + o_uuid = o_desc->ld_uuid.uuid; + n_uuid = n_desc->ld_uuid.uuid; + uuid_len = sizeof(o_desc->ld_uuid.uuid); + } + + if (unlikely(!contain_valid_fsname(o_uuid, + mlfd->mlfd_oldname, uuid_len, + o_namelen))) { + lustre_cfg_bufs_set(n_bufs, 1, o_buf, + o_buflen); + break; + } + + memcpy(n_uuid, mlfd->mlfd_newname, n_namelen); + uuid_len = strlen(o_uuid); + if (uuid_len > o_namelen) + memcpy(n_uuid + n_namelen, + o_uuid + o_namelen, + uuid_len - o_namelen); + n_uuid[uuid_len + diff] = '\0'; + lustre_cfg_bufs_set(n_bufs, 1, n_buf, o_buflen); + break; + } /* else case fall through */ + } /* else case fall through */ + } + default: { + for (i = 1; i < cnt; i++) { + o_buflen = o_lcfg->lcfg_buflens[i]; + if (o_buflen == 0) + continue; + + o_buf = lustre_cfg_buf(o_lcfg, i); + if (!contain_valid_fsname(o_buf, mlfd->mlfd_oldname, + o_buflen, o_namelen)) { + lustre_cfg_bufs_set(n_bufs, i, o_buf, o_buflen); + continue; + } + + memcpy(n_buf, mlfd->mlfd_newname, n_namelen); + if (o_buflen == o_namelen) { + lustre_cfg_bufs_set(n_bufs, i, n_buf, + n_namelen); + n_buf += cfs_size_round(n_namelen); + continue; + } + + memcpy(n_buf + n_namelen, o_buf + o_namelen, + o_buflen - o_namelen); + lustre_cfg_bufs_set(n_bufs, i, n_buf, o_buflen + diff); + n_buf += cfs_size_round(o_buflen + diff); + } + break; + } + } + + lcr = lustre_cfg_rec_new(cmd, n_bufs); + if (!lcr) + RETURN(-ENOMEM); + + lcr->lcr_cfg = *o_lcfg; + rc = llog_write(env, mlfd->mlfd_llh, &lcr->lcr_hdr, LLOG_NEXT_IDX); + lustre_cfg_rec_free(lcr); + + RETURN(rc); +} + +static int mgs_lcfg_fork_one(const struct lu_env *env, struct mgs_device *mgs, + struct mgs_direntry *mde, const char *oldname, + const char *newname) +{ + struct llog_handle *old_llh = NULL; + struct llog_handle *new_llh = NULL; + struct llog_ctxt *ctxt = NULL; + struct mgs_lcfg_fork_data *mlfd = NULL; + char *name_buf = NULL; + int name_buflen; + int old_namelen = strlen(oldname); + int new_namelen = strlen(newname); + int rc; + ENTRY; + + name_buflen = mde->mde_len + new_namelen - old_namelen; + OBD_ALLOC(name_buf, name_buflen); + if (!name_buf) + RETURN(-ENOMEM); + + memcpy(name_buf, newname, new_namelen); + memcpy(name_buf + new_namelen, mde->mde_name + old_namelen, + mde->mde_len - old_namelen); + + CDEBUG(D_MGS, "Fork the config-log from %s to %s\n", + mde->mde_name, name_buf); + + ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT); + LASSERT(ctxt); + + rc = llog_open_create(env, ctxt, &new_llh, NULL, name_buf); + if (rc) + GOTO(out, rc); + + rc = llog_init_handle(env, new_llh, LLOG_F_IS_PLAIN, NULL); + if (rc) + GOTO(out, rc); + + if (unlikely(mgs_log_is_empty(env, mgs, mde->mde_name))) + GOTO(out, rc = 0); + + rc = llog_open(env, ctxt, &old_llh, NULL, mde->mde_name, + LLOG_OPEN_EXISTS); + if (rc) + GOTO(out, rc); + + rc = llog_init_handle(env, old_llh, LLOG_F_IS_PLAIN, NULL); + if (rc) + GOTO(out, rc); + + new_llh->lgh_hdr->llh_tgtuuid = old_llh->lgh_hdr->llh_tgtuuid; + + OBD_ALLOC(mlfd, LLOG_MIN_CHUNK_SIZE); + if (!mlfd) + GOTO(out, rc = -ENOMEM); + + mlfd->mlfd_mgs = mgs; + mlfd->mlfd_llh = new_llh; + mlfd->mlfd_oldname = oldname; + mlfd->mlfd_newname = newname; + + rc = llog_process(env, old_llh, mgs_lcfg_fork_handler, mlfd, NULL); + OBD_FREE(mlfd, LLOG_MIN_CHUNK_SIZE); + + GOTO(out, rc); + +out: + if (old_llh) + llog_close(env, old_llh); + if (new_llh) + llog_close(env, new_llh); + if (name_buf) + OBD_FREE(name_buf, name_buflen); + if (ctxt) + llog_ctxt_put(ctxt); + + return rc; +} + +int mgs_lcfg_fork(const struct lu_env *env, struct mgs_device *mgs, + const char *oldname, const char *newname) +{ + struct list_head log_list; + struct mgs_direntry *dirent, *n; + int olen = strlen(oldname); + int nlen = strlen(newname); + int count = 0; + int rc = 0; + ENTRY; + + if (unlikely(!oldname || oldname[0] == '\0' || + !newname || newname[0] == '\0')) + RETURN(-EINVAL); + + if (strcmp(oldname, newname) == 0) + RETURN(-EINVAL); + + /* lock it to prevent fork/erase/register in parallel. */ + mutex_lock(&mgs->mgs_mutex); + + rc = class_dentry_readdir(env, mgs, &log_list); + if (rc) { + mutex_unlock(&mgs->mgs_mutex); + RETURN(rc); + } + + if (list_empty(&log_list)) { + mutex_unlock(&mgs->mgs_mutex); + RETURN(-ENOENT); + } + + list_for_each_entry_safe(dirent, n, &log_list, mde_list) { + char *ptr; + + ptr = strrchr(dirent->mde_name, '-'); + if (ptr) { + int tlen = ptr - dirent->mde_name; + + if (tlen == nlen && + strncmp(newname, dirent->mde_name, tlen) == 0) + GOTO(out, rc = -EEXIST); + + if (tlen == olen && + strncmp(oldname, dirent->mde_name, tlen) == 0) + continue; + } + + list_del_init(&dirent->mde_list); + mgs_direntry_free(dirent); + } + + if (list_empty(&log_list)) { + mutex_unlock(&mgs->mgs_mutex); + RETURN(-ENOENT); + } + + list_for_each_entry(dirent, &log_list, mde_list) { + rc = mgs_lcfg_fork_one(env, mgs, dirent, oldname, newname); + if (rc) + break; + + count++; + } + +out: + mutex_unlock(&mgs->mgs_mutex); + + list_for_each_entry_safe(dirent, n, &log_list, mde_list) { + list_del_init(&dirent->mde_list); + mgs_direntry_free(dirent); + } + + if (rc && count > 0) + mgs_erase_logs(env, mgs, newname); + + RETURN(rc); +} + +int mgs_lcfg_erase(const struct lu_env *env, struct mgs_device *mgs, + const char *fsname) +{ + int rc; + ENTRY; + + if (unlikely(!fsname || fsname[0] == '\0')) + RETURN(-EINVAL); + + rc = mgs_erase_logs(env, mgs, fsname); + + RETURN(rc); +} + +static int mgs_xattr_del(const struct lu_env *env, struct dt_object *obj) +{ + struct dt_device *dev; + struct thandle *th = NULL; + int rc = 0; + + ENTRY; + + dev = container_of0(obj->do_lu.lo_dev, struct dt_device, dd_lu_dev); + th = dt_trans_create(env, dev); + if (IS_ERR(th)) + RETURN(PTR_ERR(th)); + + rc = dt_declare_xattr_del(env, obj, XATTR_TARGET_RENAME, th); + if (rc) + GOTO(stop, rc); + + rc = dt_trans_start_local(env, dev, th); + if (rc) + GOTO(stop, rc); + + dt_write_lock(env, obj, 0); + rc = dt_xattr_del(env, obj, XATTR_TARGET_RENAME, th); + + GOTO(unlock, rc); + +unlock: + dt_write_unlock(env, obj); + +stop: + dt_trans_stop(env, dev, th); + + return rc; +} + +int mgs_lcfg_rename(const struct lu_env *env, struct mgs_device *mgs) +{ + struct list_head log_list; + struct mgs_direntry *dirent, *n; + char fsname[16]; + struct lu_buf buf = { + .lb_buf = fsname, + .lb_len = sizeof(fsname) + }; + int rc = 0; + + ENTRY; + + rc = class_dentry_readdir(env, mgs, &log_list); + if (rc) + RETURN(rc); + + if (list_empty(&log_list)) + RETURN(0); + + list_for_each_entry_safe(dirent, n, &log_list, mde_list) { + struct dt_object *o = NULL; + char oldname[16]; + char *ptr; + int len; + + list_del_init(&dirent->mde_list); + ptr = strrchr(dirent->mde_name, '-'); + if (!ptr) + goto next; + + len = ptr - dirent->mde_name; + if (unlikely(len >= sizeof(oldname))) { + CDEBUG(D_MGS, "Skip invalid configuration file %s\n", + dirent->mde_name); + goto next; + } + + o = local_file_find(env, mgs->mgs_los, mgs->mgs_configs_dir, + dirent->mde_name); + if (IS_ERR(o)) { + rc = PTR_ERR(o); + CDEBUG(D_MGS, "Fail to locate file %s: rc = %d\n", + dirent->mde_name, rc); + goto next; + } + + rc = dt_xattr_get(env, o, &buf, XATTR_TARGET_RENAME); + if (rc < 0) { + if (rc == -ENODATA) + rc = 0; + else + CDEBUG(D_MGS, + "Fail to get EA for %s: rc = %d\n", + dirent->mde_name, rc); + goto next; + } + + if (unlikely(rc == len && + memcmp(fsname, dirent->mde_name, len) == 0)) { + /* The new fsname is the same as the old one. */ + rc = mgs_xattr_del(env, o); + goto next; + } + + memcpy(oldname, dirent->mde_name, len); + oldname[len] = '\0'; + fsname[rc] = '\0'; + rc = mgs_lcfg_fork_one(env, mgs, dirent, oldname, fsname); + if (rc && rc != -EEXIST) { + CDEBUG(D_MGS, "Fail to fork %s: rc = %d\n", + dirent->mde_name, rc); + goto next; + } + + rc = mgs_erase_log(env, mgs, dirent->mde_name); + if (rc) { + CDEBUG(D_MGS, "Fail to erase old %s: rc = %d\n", + dirent->mde_name, rc); + /* keep it there if failed to remove it. */ + rc = 0; + } + +next: + if (o && !IS_ERR(o)) + lu_object_put(env, &o->do_lu); + + mgs_direntry_free(dirent); + if (rc) + break; + } + + list_for_each_entry_safe(dirent, n, &log_list, mde_list) { + list_del_init(&dirent->mde_list); + mgs_direntry_free(dirent); + } + + RETURN(rc); +} + /* from llog_swab */ static void print_lustre_cfg(struct lustre_cfg *lcfg) { @@ -3924,33 +4708,36 @@ static void print_lustre_cfg(struct lustre_cfg *lcfg) /* Setup _mgs fsdb and log */ -int mgs__mgs_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs, - struct fs_db *fsdb) +int mgs__mgs_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs) { - int rc; + struct fs_db *fsdb = NULL; + int rc; ENTRY; rc = mgs_find_or_make_fsdb(env, mgs, MGSSELF_NAME, &fsdb); + if (!rc) + mgs_put_fsdb(mgs, fsdb); RETURN(rc); } /* Setup params fsdb and log */ -int mgs_params_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs, - struct fs_db *fsdb) +int mgs_params_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs) { - struct llog_handle *params_llh = NULL; - int rc; + struct fs_db *fsdb = NULL; + struct llog_handle *params_llh = NULL; + int rc; ENTRY; rc = mgs_find_or_make_fsdb(env, mgs, PARAMS_FILENAME, &fsdb); - if (fsdb != NULL) { + if (!rc) { mutex_lock(&fsdb->fsdb_mutex); rc = record_start_log(env, mgs, ¶ms_llh, PARAMS_FILENAME); - if (rc == 0) + if (!rc) rc = record_end_log(env, ¶ms_llh); mutex_unlock(&fsdb->fsdb_mutex); + mgs_put_fsdb(mgs, fsdb); } RETURN(rc); @@ -3960,7 +4747,10 @@ int mgs_params_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs, */ int mgs_params_fsdb_cleanup(const struct lu_env *env, struct mgs_device *mgs) { - return mgs_erase_logs(env, mgs, PARAMS_FILENAME); + int rc; + + rc = mgs_erase_logs(env, mgs, PARAMS_FILENAME); + return rc == -ENOENT ? 0 : rc; } /* Set a permanent (config log) param for a target or fs @@ -3970,13 +4760,14 @@ int mgs_params_fsdb_cleanup(const struct lu_env *env, struct mgs_device *mgs) int mgs_setparam(const struct lu_env *env, struct mgs_device *mgs, struct lustre_cfg *lcfg, char *fsname) { - struct fs_db *fsdb; - struct mgs_target_info *mti; - char *devname, *param; + struct fs_db *fsdb = NULL; + struct mgs_target_info *mti = NULL; + char *devname, *param; char *ptr; const char *tmp; __u32 index; int rc = 0; + bool free = false; ENTRY; print_lustre_cfg(lcfg); @@ -4020,16 +4811,16 @@ int mgs_setparam(const struct lu_env *env, struct mgs_device *mgs, if (lcfg->lcfg_command != LCFG_SET_PARAM && !test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags) && test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) { - CERROR("No filesystem targets for %s. cfg_device from lctl " - "is '%s'\n", fsname, devname); - mgs_free_fsdb(mgs, fsdb); - RETURN(-EINVAL); - } + CERROR("No filesystem targets for %s. cfg_device from lctl " + "is '%s'\n", fsname, devname); + free = true; + GOTO(out, rc = -EINVAL); + } - /* Create a fake mti to hold everything */ - OBD_ALLOC_PTR(mti); - if (!mti) - GOTO(out, rc = -ENOMEM); + /* Create a fake mti to hold everything */ + OBD_ALLOC_PTR(mti); + if (!mti) + GOTO(out, rc = -ENOMEM); if (strlcpy(mti->mti_fsname, fsname, sizeof(mti->mti_fsname)) >= sizeof(mti->mti_fsname)) GOTO(out, rc = -E2BIG); @@ -4046,7 +4837,7 @@ int mgs_setparam(const struct lu_env *env, struct mgs_device *mgs, else /* Strip -osc or -mdc suffix from svname */ if (server_make_name(rc, mti->mti_stripe_index, mti->mti_fsname, - mti->mti_svname)) + mti->mti_svname, sizeof(mti->mti_svname))) GOTO(out, rc = -EINVAL); /* * Revoke lock so everyone updates. Should be alright if @@ -4069,8 +4860,16 @@ int mgs_setparam(const struct lu_env *env, struct mgs_device *mgs, } out: - OBD_FREE_PTR(mti); - RETURN(rc); + if (mti) + OBD_FREE_PTR(mti); + + if (fsdb) { + if (free) + mgs_unlink_fsdb(mgs, fsdb); + mgs_put_fsdb(mgs, fsdb); + } + + RETURN(rc); } static int mgs_write_log_pool(const struct lu_env *env, @@ -4133,6 +4932,23 @@ int mgs_nodemap_cmd(const struct lu_env *env, struct mgs_device *mgs, bool_switch = simple_strtoul(param, NULL, 10); rc = nodemap_set_allow_root(nodemap_name, bool_switch); break; + case LCFG_NODEMAP_DENY_UNKNOWN: + bool_switch = simple_strtoul(param, NULL, 10); + rc = nodemap_set_deny_unknown(nodemap_name, bool_switch); + break; + case LCFG_NODEMAP_MAP_MODE: + if (strcmp("both", param) == 0) + rc = nodemap_set_mapping_mode(nodemap_name, + NODEMAP_MAP_BOTH); + else if (strcmp("uid_only", param) == 0) + rc = nodemap_set_mapping_mode(nodemap_name, + NODEMAP_MAP_UID_ONLY); + else if (strcmp("gid_only", param) == 0) + rc = nodemap_set_mapping_mode(nodemap_name, + NODEMAP_MAP_GID_ONLY); + else + rc = -EINVAL; + break; case LCFG_NODEMAP_TRUSTED: bool_switch = simple_strtoul(param, NULL, 10); rc = nodemap_set_trust_client_ids(nodemap_name, bool_switch); @@ -4189,18 +5005,21 @@ int mgs_pool_cmd(const struct lu_env *env, struct mgs_device *mgs, char *label = NULL, *canceled_label = NULL; int label_sz; struct mgs_target_info *mti = NULL; - int rc, i; - ENTRY; + bool checked = false; + bool locked = false; + bool free = false; + int rc, i; + ENTRY; rc = mgs_find_or_make_fsdb(env, mgs, fsname, &fsdb); - if (rc) { - CERROR("Can't get db for %s\n", fsname); - RETURN(rc); - } + if (rc) { + CERROR("Can't get db for %s\n", fsname); + RETURN(rc); + } if (test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) { - CERROR("%s is not defined\n", fsname); - mgs_free_fsdb(mgs, fsdb); - RETURN(-EINVAL); + CERROR("%s is not defined\n", fsname); + free = true; + GOTO(out_fsdb, rc = -EINVAL); } label_sz = 10 + strlen(fsname) + strlen(poolname); @@ -4217,8 +5036,8 @@ int mgs_pool_cmd(const struct lu_env *env, struct mgs_device *mgs, } OBD_ALLOC(label, label_sz); - if (label == NULL) - RETURN(-ENOMEM); + if (!label) + GOTO(out_fsdb, rc = -ENOMEM); switch(cmd) { case LCFG_POOL_NEW: @@ -4251,53 +5070,67 @@ int mgs_pool_cmd(const struct lu_env *env, struct mgs_device *mgs, break; } - if (canceled_label != NULL) { - OBD_ALLOC_PTR(mti); - if (mti == NULL) - GOTO(out_cancel, rc = -ENOMEM); - } + OBD_ALLOC_PTR(mti); + if (mti == NULL) + GOTO(out_cancel, rc = -ENOMEM); + strncpy(mti->mti_svname, "lov pool", sizeof(mti->mti_svname)); mutex_lock(&fsdb->fsdb_mutex); - /* write pool def to all MDT logs */ - for (i = 0; i < INDEX_MAP_SIZE * 8; i++) { + locked = true; + /* write pool def to all MDT logs */ + for (i = 0; i < INDEX_MAP_SIZE * 8; i++) { if (test_bit(i, fsdb->fsdb_mdt_index_map)) { rc = name_create_mdt_and_lov(&logname, &lovname, fsdb, i); - if (rc) { - mutex_unlock(&fsdb->fsdb_mutex); + if (rc) GOTO(out_mti, rc); + + if (!checked && (canceled_label == NULL)) { + rc = mgs_check_marker(env, mgs, fsdb, mti, + logname, lovname, label); + if (rc) { + name_destroy(&logname); + name_destroy(&lovname); + GOTO(out_mti, + rc = (rc == LLOG_PROC_BREAK ? + -EEXIST : rc)); + } + checked = true; } - if (canceled_label != NULL) { - strcpy(mti->mti_svname, "lov pool"); + if (canceled_label != NULL) rc = mgs_modify(env, mgs, fsdb, mti, logname, lovname, canceled_label, CM_SKIP); - } if (rc >= 0) rc = mgs_write_log_pool(env, mgs, logname, fsdb, lovname, cmd, fsname, poolname, ostname, label); - name_destroy(&logname); - name_destroy(&lovname); - if (rc) { - mutex_unlock(&fsdb->fsdb_mutex); + name_destroy(&logname); + name_destroy(&lovname); + if (rc) GOTO(out_mti, rc); - } - } - } + } + } rc = name_create(&logname, fsname, "-client"); - if (rc) { - mutex_unlock(&fsdb->fsdb_mutex); + if (rc) GOTO(out_mti, rc); + + if (!checked && (canceled_label == NULL)) { + rc = mgs_check_marker(env, mgs, fsdb, mti, logname, + fsdb->fsdb_clilov, label); + if (rc) { + name_destroy(&logname); + GOTO(out_mti, rc = (rc == LLOG_PROC_BREAK ? + -EEXIST : rc)); + } } if (canceled_label != NULL) { rc = mgs_modify(env, mgs, fsdb, mti, logname, fsdb->fsdb_clilov, canceled_label, CM_SKIP); if (rc < 0) { - mutex_unlock(&fsdb->fsdb_mutex); name_destroy(&logname); GOTO(out_mti, rc); } @@ -4306,18 +5139,27 @@ int mgs_pool_cmd(const struct lu_env *env, struct mgs_device *mgs, rc = mgs_write_log_pool(env, mgs, logname, fsdb, fsdb->fsdb_clilov, cmd, fsname, poolname, ostname, label); mutex_unlock(&fsdb->fsdb_mutex); + locked = false; name_destroy(&logname); - /* request for update */ + /* request for update */ mgs_revoke_lock(mgs, fsdb, CONFIG_T_CONFIG); - EXIT; + GOTO(out_mti, rc); + out_mti: - if (mti != NULL) - OBD_FREE_PTR(mti); + if (locked) + mutex_unlock(&fsdb->fsdb_mutex); + if (mti != NULL) + OBD_FREE_PTR(mti); out_cancel: if (canceled_label != NULL) OBD_FREE(canceled_label, label_sz); out_label: OBD_FREE(label, label_sz); - return rc; +out_fsdb: + if (free) + mgs_unlink_fsdb(mgs, fsdb); + mgs_put_fsdb(mgs, fsdb); + + return rc; }