X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fmgs%2Fmgs_fs.c;h=338858e1254ede601446ab5258ece4afcbdaa750;hp=ff708e08f5b84487edc5e48ee016dfbe7b6280b8;hb=a68e117a54af82f209aed46a822f8346a3e0703f;hpb=e67c6e366752611ffd2baeb7cefa24c9f289eb78 diff --git a/lustre/mgs/mgs_fs.c b/lustre/mgs/mgs_fs.c index ff708e0..338858e 100644 --- a/lustre/mgs/mgs_fs.c +++ b/lustre/mgs/mgs_fs.c @@ -1,6 +1,4 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * +/* * GPL HEADER START * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -26,8 +24,10 @@ * GPL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2011, 2015, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -38,60 +38,62 @@ * Lustre Management Server (MGS) filesystem interface code * * Author: Nathan Rutman + * Author: Alex Zhuravlev */ -#ifndef EXPORT_SYMTAB -# define EXPORT_SYMTAB -#endif #define DEBUG_SUBSYSTEM S_MGS -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include "mgs_internal.h" -static int mgs_export_stats_init(struct obd_device *obd, struct obd_export *exp, - void *localdata) +/** + * Initialize MGS per-export statistics. + * + * This function sets up procfs entries for various MGS export counters. These + * counters are for per-client statistics tracked on the server. + * + * \param[in] obd OBD device + * \param[in] exp OBD export + * \param[in] localdata NID of client + * + * \retval 0 if successful + * \retval negative value on error + */ +int mgs_export_stats_init(struct obd_device *obd, struct obd_export *exp, + void *localdata) { - lnet_nid_t *client_nid = localdata; - int rc, newnid; - ENTRY; - - rc = lprocfs_exp_setup(exp, client_nid, &newnid); - if (rc) { - /* Mask error for already created - * /proc entries */ - if (rc == -EALREADY) - rc = 0; - RETURN(rc); - } - - if (newnid) { - /* Always add in ldlm_stats */ - exp->exp_nid_stats->nid_ldlm_stats = - lprocfs_alloc_stats(LDLM_LAST_OPC - LDLM_FIRST_OPC, - LPROCFS_STATS_FLAG_NOPERCPU); - if (exp->exp_nid_stats->nid_ldlm_stats == NULL) - GOTO(clean, rc = -ENOMEM); - lprocfs_init_ldlm_stats(exp->exp_nid_stats->nid_ldlm_stats); - rc = lprocfs_register_stats(exp->exp_nid_stats->nid_proc, - "ldlm_stats", - exp->exp_nid_stats->nid_ldlm_stats); - if (rc) - GOTO(clean, rc); - } - RETURN(0); -clean: - lprocfs_exp_cleanup(exp); - return rc; + lnet_nid_t *client_nid = localdata; + struct nid_stat *stats; + int rc; + ENTRY; + + rc = lprocfs_exp_setup(exp, client_nid); + if (rc != 0) + /* Mask error for already created /proc entries */ + RETURN(rc == -EALREADY ? 0 : rc); + + stats = exp->exp_nid_stats; + stats->nid_stats = lprocfs_alloc_stats(NUM_OBD_STATS + LPROC_MGS_LAST, + LPROCFS_STATS_FLAG_NOPERCPU); + if (stats->nid_stats == NULL) + RETURN(-ENOMEM); + + lprocfs_init_ops_stats(LPROC_MGS_LAST, stats->nid_stats); + + mgs_stats_counter_init(stats->nid_stats); + + rc = lprocfs_register_stats(stats->nid_proc, "stats", stats->nid_stats); + if (rc != 0) { + lprocfs_free_stats(&stats->nid_stats); + GOTO(out, rc); + } + + rc = lprocfs_nid_ldlm_stats_init(stats); + if (rc != 0) + GOTO(out, rc); + +out: + RETURN(rc); } /** @@ -100,9 +102,9 @@ clean: * crash all connections are treated as new connections. */ int mgs_client_add(struct obd_device *obd, struct obd_export *exp, - void *localdata) + void *localdata) { - return mgs_export_stats_init(obd, exp, localdata); + return 0; } /* Remove client export data from the MGS */ @@ -111,152 +113,138 @@ int mgs_client_free(struct obd_export *exp) return 0; } -/* Same as mds_fid2dentry */ -/* Look up an entry by inode number. */ -/* this function ONLY returns valid dget'd dentries with an initialized inode - or errors */ -static struct dentry *mgs_fid2dentry(struct mgs_obd *mgs, - __u64 ino, __u32 gen) -{ - char fid_name[32]; - struct inode *inode; - struct dentry *result; - ENTRY; - - CDEBUG(D_DENTRY, "--> mgs_fid2dentry: ino/gen %lu/%u, sb %p\n", - (unsigned long)ino, gen, mgs->mgs_sb); - - if (ino == 0) - RETURN(ERR_PTR(-ESTALE)); - - snprintf(fid_name, sizeof(fid_name), "0x%lx", (unsigned long)ino); - - /* under ext3 this is neither supposed to return bad inodes nor NULL - inodes. */ - result = ll_lookup_one_len(fid_name, mgs->mgs_fid_de, strlen(fid_name)); - if (IS_ERR(result)) - RETURN(result); - - inode = result->d_inode; - if (!inode) - RETURN(ERR_PTR(-ENOENT)); - - if (inode->i_generation == 0 || inode->i_nlink == 0) { - LCONSOLE_WARN("Found inode with zero generation or link -- this" - " may indicate disk corruption (inode: %lu, link:" - " %lu, count: %d)\n", inode->i_ino, - (unsigned long)inode->i_nlink, - atomic_read(&inode->i_count)); - l_dput(result); - RETURN(ERR_PTR(-ENOENT)); - } - - if (gen && inode->i_generation != gen) { - /* we didn't find the right inode.. */ - CDEBUG(D_INODE, "found wrong generation: inode %lu, link: %lu, " - "count: %d, generation %u/%u\n", inode->i_ino, - (unsigned long)inode->i_nlink, - atomic_read(&inode->i_count), - inode->i_generation, gen); - l_dput(result); - RETURN(ERR_PTR(-ENOENT)); - } - - RETURN(result); -} - -static struct dentry *mgs_lvfs_fid2dentry(__u64 id, __u32 gen, - __u64 gr, void *data) -{ - struct obd_device *obd = data; - return mgs_fid2dentry(&obd->u.mgs, id, gen); -} - -struct lvfs_callback_ops mgs_lvfs_ops = { - l_fid2dentry: mgs_lvfs_fid2dentry, -}; - -int mgs_fs_setup(struct obd_device *obd, struct vfsmount *mnt) +int mgs_fs_setup(const struct lu_env *env, struct mgs_device *mgs) { - struct mgs_obd *mgs = &obd->u.mgs; - struct lvfs_run_ctxt saved; - struct dentry *dentry; - int rc; - ENTRY; - - /* FIXME what's this? Do I need it? */ - rc = cfs_cleanup_group_info(); - if (rc) - RETURN(rc); - - mgs->mgs_vfsmnt = mnt; - mgs->mgs_sb = mnt->mnt_root->d_inode->i_sb; - - fsfilt_setup(obd, mgs->mgs_sb); - - OBD_SET_CTXT_MAGIC(&obd->obd_lvfs_ctxt); - obd->obd_lvfs_ctxt.pwdmnt = mnt; - obd->obd_lvfs_ctxt.pwd = mnt->mnt_root; - obd->obd_lvfs_ctxt.fs = get_ds(); - obd->obd_lvfs_ctxt.cb_ops = mgs_lvfs_ops; - - push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - - /* Setup the configs dir */ - dentry = simple_mkdir(current->fs->pwd, mnt, MOUNT_CONFIGS_DIR, 0777, 1); - if (IS_ERR(dentry)) { - rc = PTR_ERR(dentry); - CERROR("cannot create %s directory: rc = %d\n", - MOUNT_CONFIGS_DIR, rc); - GOTO(err_pop, rc); - } - mgs->mgs_configs_dir = dentry; - - /* Need the iopen dir for fid2dentry, required by - LLOG_ORIGIN_HANDLE_READ_HEADER */ - dentry = lookup_one_len("__iopen__", current->fs->pwd, - strlen("__iopen__")); - if (IS_ERR(dentry)) { - rc = PTR_ERR(dentry); - CERROR("cannot lookup __iopen__ directory: rc = %d\n", rc); - GOTO(err_configs, rc); - } - mgs->mgs_fid_de = dentry; - if (!dentry->d_inode || is_bad_inode(dentry->d_inode)) { - rc = -ENOENT; - CERROR("__iopen__ directory has no inode? rc = %d\n", rc); - GOTO(err_fid, rc); - } - -err_pop: - pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - return rc; -err_fid: - dput(mgs->mgs_fid_de); -err_configs: - dput(mgs->mgs_configs_dir); - goto err_pop; + struct lu_fid fid; + struct dt_object *o; + struct lu_fid rfid; + struct dt_object *root; + struct dt_object *nm_config_file_obj; + struct nm_config_file *nm_config_file; + int rc; + + ENTRY; + + OBD_SET_CTXT_MAGIC(&mgs->mgs_obd->obd_lvfs_ctxt); + mgs->mgs_obd->obd_lvfs_ctxt.dt = mgs->mgs_bottom; + + /* XXX: fix when support for N:1 layering is implemented */ + LASSERT(mgs->mgs_dt_dev.dd_lu_dev.ld_site); + mgs->mgs_dt_dev.dd_lu_dev.ld_site->ls_top_dev = + &mgs->mgs_dt_dev.dd_lu_dev; + + /* Setup the configs dir */ + fid.f_seq = FID_SEQ_LOCAL_NAME; + fid.f_oid = 1; + fid.f_ver = 0; + rc = local_oid_storage_init(env, mgs->mgs_bottom, &fid, &mgs->mgs_los); + if (rc) + GOTO(out, rc); + + rc = dt_root_get(env, mgs->mgs_bottom, &rfid); + if (rc) + GOTO(out_los, rc); + + root = dt_locate_at(env, mgs->mgs_bottom, &rfid, + &mgs->mgs_dt_dev.dd_lu_dev, NULL); + if (unlikely(IS_ERR(root))) + GOTO(out_los, rc = PTR_ERR(root)); + + o = local_file_find_or_create(env, mgs->mgs_los, root, + MOUNT_CONFIGS_DIR, + S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO); + if (IS_ERR(o)) + GOTO(out_root, rc = PTR_ERR(o)); + + if (!dt_try_as_dir(env, o)) { + lu_object_put(env, &o->do_lu); + GOTO(out_root, rc = -ENOTDIR); + } + + mgs->mgs_configs_dir = o; + + /* colocated MDT will cache config in target / dir */ + nm_config_file_obj = local_index_find_or_create(env, mgs->mgs_los, + mgs->mgs_configs_dir, + LUSTRE_NODEMAP_NAME, + S_IFREG | S_IRUGO | + S_IWUSR, + &dt_nodemap_features); + if (IS_ERR(nm_config_file_obj)) + GOTO(out_configs, rc = PTR_ERR(nm_config_file_obj)); + + if (nm_config_file_obj->do_index_ops == NULL) { + rc = nm_config_file_obj->do_ops->do_index_try(env, + nm_config_file_obj, + &dt_nodemap_features); + if (rc < 0) { + lu_object_put(env, &nm_config_file_obj->do_lu); + GOTO(out_configs, rc); + } + } + nm_config_file = nm_config_file_register(env, nm_config_file_obj, + mgs->mgs_los, NCFT_MGS); + if (IS_ERR(nm_config_file)) { + lu_object_put(env, &nm_config_file_obj->do_lu); + CERROR("%s: error loading nodemap config file, file must be " + "removed via ldiskfs: rc = %ld\n", + mgs->mgs_obd->obd_name, PTR_ERR(nm_config_file)); + GOTO(out_configs, rc = PTR_ERR(nm_config_file)); + } + mgs->mgs_obd->u.obt.obt_nodemap_config_file = nm_config_file; + + /* create directory to store nid table versions */ + o = local_file_find_or_create(env, mgs->mgs_los, root, MGS_NIDTBL_DIR, + S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO); + if (IS_ERR(o)) + GOTO(out_nm, rc = PTR_ERR(o)); + + mgs->mgs_nidtbl_dir = o; + +out_nm: + if (rc < 0) { + nm_config_file_deregister(env, nm_config_file, NCFT_MGS); + mgs->mgs_obd->u.obt.obt_nodemap_config_file = NULL; + } +out_configs: + if (rc < 0) { + lu_object_put(env, &mgs->mgs_configs_dir->do_lu); + mgs->mgs_configs_dir = NULL; + } +out_root: + lu_object_put(env, &root->do_lu); +out_los: + if (rc) { + local_oid_storage_fini(env, mgs->mgs_los); + mgs->mgs_los = NULL; + } +out: + mgs->mgs_dt_dev.dd_lu_dev.ld_site->ls_top_dev = NULL; + + return rc; } -int mgs_fs_cleanup(struct obd_device *obd) +int mgs_fs_cleanup(const struct lu_env *env, struct mgs_device *mgs) { - struct mgs_obd *mgs = &obd->u.mgs; - struct lvfs_run_ctxt saved; - int rc = 0; - - class_disconnect_exports(obd); /* cleans up client info too */ - - push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - - if (mgs->mgs_configs_dir) { - l_dput(mgs->mgs_configs_dir); - mgs->mgs_configs_dir = NULL; - } - - dput(mgs->mgs_fid_de); - shrink_dcache_sb(mgs->mgs_sb); - - pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - - return rc; + if (mgs->mgs_configs_dir) { + lu_object_put(env, &mgs->mgs_configs_dir->do_lu); + mgs->mgs_configs_dir = NULL; + } + if (mgs->mgs_nidtbl_dir) { + lu_object_put(env, &mgs->mgs_nidtbl_dir->do_lu); + mgs->mgs_nidtbl_dir = NULL; + } + if (mgs->mgs_obd->u.obt.obt_nodemap_config_file != NULL) { + nm_config_file_deregister(env, + mgs->mgs_obd->u.obt.obt_nodemap_config_file, + NCFT_MGS); + mgs->mgs_obd->u.obt.obt_nodemap_config_file = NULL; + } + + if (mgs->mgs_los) { + local_oid_storage_fini(env, mgs->mgs_los); + mgs->mgs_los = NULL; + } + + return 0; }