⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mgc_request.c

📁 lustre 1.6.5 source code
💻 C
📖 第 1 页 / 共 3 页
字号:
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * *  lustre/mgc/mgc_request.c *  Lustre Management Client * *  Copyright (C) 2006 Cluster File Systems, Inc. *   Author: Nathan Rutman <nathan@clusterfs.com> * *   This file is part of Lustre, http://www.lustre.org * *   Lustre is free software; you can redistribute it and/or *   modify it under the terms of version 2 of the GNU General Public *   License as published by the Free Software Foundation. * *   Lustre is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with Lustre; if not, write to the Free Software *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */#ifndef EXPORT_SYMTAB# define EXPORT_SYMTAB#endif#define DEBUG_SUBSYSTEM S_MGC#define D_MGC D_CONFIG /*|D_WARNING*/#ifdef __KERNEL__# include <linux/module.h># include <linux/pagemap.h># include <linux/miscdevice.h># include <linux/init.h>#else# include <liblustre.h>#endif#include <obd_class.h>#include <lustre_dlm.h>#include <lprocfs_status.h>#include <lustre_log.h>#include <lustre_fsfilt.h>#include <lustre_disk.h>#include "mgc_internal.h"static int mgc_name2resid(char *name, int len, struct ldlm_res_id *res_id){        __u64 resname = 0;        if (len > 8) {                CERROR("name too long: %s\n", name);                return -EINVAL;        }        if (len <= 0) {                CERROR("missing name: %s\n", name);                return -EINVAL;        }        memcpy(&resname, name, len);        memset(res_id, 0, sizeof(*res_id));        /* Always use the same endianness for the resid */        res_id->name[0] = cpu_to_le64(resname);        CDEBUG(D_MGC, "log %s to resid "LPX64"/"LPX64" (%.8s)\n", name,               res_id->name[0], res_id->name[1], (char *)&res_id->name[0]);        return 0;}int mgc_fsname2resid(char *fsname, struct ldlm_res_id *res_id){        /* fsname is at most 8 chars long, maybe contain "-".         * e.g. "lustre", "CFS-000" */        return mgc_name2resid(fsname, strlen(fsname), res_id);}EXPORT_SYMBOL(mgc_fsname2resid);int mgc_logname2resid(char *logname, struct ldlm_res_id *res_id){        char *name_end;        int len;        /* logname consists of "fsname-nodetype".         * e.g. "lustre-MDT0001", "CFS-000-client" */        name_end = strrchr(logname, '-');        LASSERT(name_end);        len = name_end - logname;        return mgc_name2resid(logname, len, res_id);}/********************** config llog list **********************/static struct list_head config_llog_list = LIST_HEAD_INIT(config_llog_list);static spinlock_t       config_list_lock = SPIN_LOCK_UNLOCKED;/* Take a reference to a config log */static int config_log_get(struct config_llog_data *cld){        ENTRY;        if (cld->cld_stopping)                RETURN(1);        atomic_inc(&cld->cld_refcount);        CDEBUG(D_INFO, "log %s refs %d\n", cld->cld_logname,               atomic_read(&cld->cld_refcount));        RETURN(0);}/* Drop a reference to a config log.  When no longer referenced,    we can free the config log data */static void config_log_put(struct config_llog_data *cld){        ENTRY;        CDEBUG(D_INFO, "log %s refs %d\n", cld->cld_logname,               atomic_read(&cld->cld_refcount));        if (atomic_dec_and_test(&cld->cld_refcount)) {                CDEBUG(D_MGC, "dropping config log %s\n", cld->cld_logname);                class_export_put(cld->cld_mgcexp);                spin_lock(&config_list_lock);                list_del(&cld->cld_list_chain);                spin_unlock(&config_list_lock);                OBD_FREE(cld->cld_logname, strlen(cld->cld_logname) + 1);                if (cld->cld_cfg.cfg_instance != NULL)                        OBD_FREE(cld->cld_cfg.cfg_instance,                                  strlen(cld->cld_cfg.cfg_instance) + 1);                OBD_FREE(cld, sizeof(*cld));        }        EXIT;}/* Find a config log by name */static struct config_llog_data *config_log_find(char *logname,                                                struct config_llog_instance *cfg){        struct list_head *tmp;        struct config_llog_data *cld;        char *logid = logname;        int match_instance = 0;        ENTRY;        if (cfg && cfg->cfg_instance) {                match_instance++;                logid = cfg->cfg_instance;        }        if (!logid) {                CERROR("No log specified\n");                RETURN(ERR_PTR(-EINVAL));        }        spin_lock(&config_list_lock);        list_for_each(tmp, &config_llog_list) {                cld = list_entry(tmp, struct config_llog_data, cld_list_chain);                if (match_instance && cld->cld_cfg.cfg_instance &&                     strcmp(logid, cld->cld_cfg.cfg_instance) == 0)                        goto out_found;                if (!match_instance &&                      strcmp(logid, cld->cld_logname) == 0)                        goto out_found;        }        spin_unlock(&config_list_lock);        CDEBUG(D_CONFIG, "can't get log %s\n", logid);        RETURN(ERR_PTR(-ENOENT));out_found:        atomic_inc(&cld->cld_refcount);        spin_unlock(&config_list_lock);        RETURN(cld);}/* Add this log to our list of active logs.    We have one active log per "mount" - client instance or servername.   Each instance may be at a different point in the log. */static int config_log_add(char *logname, struct config_llog_instance *cfg,                          struct super_block *sb){        struct config_llog_data *cld;        struct lustre_sb_info *lsi = s2lsi(sb);        int rc;        ENTRY;        CDEBUG(D_MGC, "adding config log %s:%s\n", logname, cfg->cfg_instance);                OBD_ALLOC(cld, sizeof(*cld));        if (!cld)                 RETURN(-ENOMEM);        OBD_ALLOC(cld->cld_logname, strlen(logname) + 1);        if (!cld->cld_logname) {                 OBD_FREE(cld, sizeof(*cld));                RETURN(-ENOMEM);        }        strcpy(cld->cld_logname, logname);        cld->cld_cfg = *cfg;        cld->cld_cfg.cfg_last_idx = 0;        cld->cld_cfg.cfg_flags = 0;        cld->cld_cfg.cfg_sb = sb;        atomic_set(&cld->cld_refcount, 1);                /* Keep the mgc around until we are done */        cld->cld_mgcexp = class_export_get(lsi->lsi_mgc->obd_self_export);                if (cfg->cfg_instance != NULL) {                OBD_ALLOC(cld->cld_cfg.cfg_instance,                           strlen(cfg->cfg_instance) + 1);                strcpy(cld->cld_cfg.cfg_instance, cfg->cfg_instance);        }        rc = mgc_logname2resid(logname, &cld->cld_resid);        spin_lock(&config_list_lock);        list_add(&cld->cld_list_chain, &config_llog_list);        spin_unlock(&config_list_lock);                if (rc) {                config_log_put(cld);                RETURN(rc);        }                RETURN(rc);}/* Stop watching for updates on this log. */static int config_log_end(char *logname, struct config_llog_instance *cfg){               struct config_llog_data *cld;        int rc = 0;        ENTRY;                                               cld = config_log_find(logname, cfg);        if (IS_ERR(cld))                 RETURN(PTR_ERR(cld));        /* drop the ref from the find */        config_log_put(cld);        cld->cld_stopping = 1;        /* drop the start ref */        config_log_put(cld);        CDEBUG(D_MGC, "end config log %s (%d)\n", logname ? logname : "client",               rc);        RETURN(rc);}/* reenqueue any lost locks */#define RQ_RUNNING 0x1#define RQ_NOW     0x2#define RQ_LATER   0x4#define RQ_STOP    0x8static int rq_state = 0;static cfs_waitq_t rq_waitq;static int mgc_process_log(struct obd_device *mgc,                            struct config_llog_data *cld);static int mgc_requeue_thread(void *data){        struct l_wait_info lwi_now, lwi_later;        struct config_llog_data *cld, *n;        char name[] = "ll_cfg_requeue";        int rc = 0;        ENTRY;                ptlrpc_daemonize(name);                CDEBUG(D_MGC, "Starting requeue thread\n");        lwi_later = LWI_TIMEOUT(60 * HZ, NULL, NULL);        l_wait_event(rq_waitq, rq_state & (RQ_NOW | RQ_STOP), &lwi_later);        /* Keep trying failed locks periodically */        spin_lock(&config_list_lock);        while (rq_state & (RQ_NOW | RQ_LATER)) {                /* Any new or requeued lostlocks will change the state */                rq_state &= ~(RQ_NOW | RQ_LATER);                 spin_unlock(&config_list_lock);                /* Always wait a few seconds to allow the server who                    caused the lock revocation to finish its setup, plus some                   random so everyone doesn't try to reconnect at once. */                lwi_now = LWI_TIMEOUT(3 * HZ + (ll_rand() & 0xff) * (HZ / 100),                                      NULL, NULL);                l_wait_event(rq_waitq, rq_state & RQ_STOP, &lwi_now);                                spin_lock(&config_list_lock);                list_for_each_entry_safe(cld, n, &config_llog_list,                                         cld_list_chain) {                        spin_unlock(&config_list_lock);                                                if (cld->cld_lostlock) {                                CDEBUG(D_MGC, "updating log %s\n",                                        cld->cld_logname);                                cld->cld_lostlock = 0;                                rc = mgc_process_log(cld->cld_mgcexp->exp_obd,                                                     cld);                                /* Whether we enqueued again or not in                                    mgc_process_log, we're done with the ref                                    from the old enqueue */                                        config_log_put(cld);                        }                        spin_lock(&config_list_lock);                }                spin_unlock(&config_list_lock);                                /* Wait a bit to see if anyone else needs a requeue */                l_wait_event(rq_waitq, rq_state & (RQ_NOW | RQ_STOP),                             &lwi_later);                spin_lock(&config_list_lock);        }        /* spinlock and while guarantee RQ_NOW and RQ_LATER are not set */        rq_state &= ~RQ_RUNNING;        spin_unlock(&config_list_lock);                CDEBUG(D_MGC, "Ending requeue thread\n");        RETURN(rc);}/* Add a cld to the list to requeue.  Start the requeue thread if needed.   We are responsible for dropping the config log reference from here on out. */static int mgc_requeue_add(struct config_llog_data *cld, int later){        int rc = 0;        CDEBUG(D_INFO, "log %s: requeue (l=%d r=%d sp=%d st=%x)\n",                cld->cld_logname, later, atomic_read(&cld->cld_refcount),               cld->cld_stopping, rq_state);                /* Hold lock for rq_state */        spin_lock(&config_list_lock);        cld->cld_lostlock = 1;        if (cld->cld_stopping || (rq_state & RQ_STOP)) {                spin_unlock(&config_list_lock);                config_log_put(cld);                RETURN(0);        }        if (!(rq_state & RQ_RUNNING)) {                LASSERT(rq_state == 0);                rq_state = RQ_RUNNING | (later ? RQ_LATER : RQ_NOW);                spin_unlock(&config_list_lock);                rc = cfs_kernel_thread(mgc_requeue_thread, 0,                                       CLONE_VM | CLONE_FILES);                if (rc < 0) {                        CERROR("log %s: cannot start requeue thread (%d),"                               "no more log updates!\n", cld->cld_logname, rc);                        /* Drop the ref, since the rq thread won't */                        cld->cld_lostlock = 0;                        config_log_put(cld);                        rq_state = 0;                        RETURN(rc);                }        } else {                rq_state |= later ? RQ_LATER : RQ_NOW;                spin_unlock(&config_list_lock);                cfs_waitq_signal(&rq_waitq);        }        RETURN(0);}/********************** class fns **********************/static int mgc_fs_setup(struct obd_device *obd, struct super_block *sb,                         struct vfsmount *mnt){        struct lvfs_run_ctxt saved;        struct lustre_sb_info *lsi = s2lsi(sb);        struct client_obd *cli = &obd->u.cli;        struct dentry *dentry;        char *label;        int err = 0;        ENTRY;        LASSERT(lsi);        LASSERT(lsi->lsi_srv_mnt == mnt);        /* The mgc fs exclusion sem. Only one fs can be setup at a time. */        down(&cli->cl_mgc_sem);        cleanup_group_info();        obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd));        if (IS_ERR(obd->obd_fsops)) {                up(&cli->cl_mgc_sem);                CERROR("No fstype %s rc=%ld\n", MT_STR(lsi->lsi_ldd),                        PTR_ERR(obd->obd_fsops));                RETURN(PTR_ERR(obd->obd_fsops));        }        cli->cl_mgc_vfsmnt = mnt;        fsfilt_setup(obd, mnt->mnt_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();        push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);        dentry = lookup_one_len(MOUNT_CONFIGS_DIR, current->fs->pwd,                                strlen(MOUNT_CONFIGS_DIR));        pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);        if (IS_ERR(dentry)) {                err = PTR_ERR(dentry);                CERROR("cannot lookup %s directory: rc = %d\n",                        MOUNT_CONFIGS_DIR, err);                GOTO(err_ops, err);        }        cli->cl_mgc_configs_dir = dentry;        /* We take an obd ref to insure that we can't get to mgc_cleanup           without calling mgc_fs_cleanup first. */        class_incref(obd);        label = fsfilt_get_label(obd, mnt->mnt_sb);        if (label)                CDEBUG(D_MGC, "MGC using disk labelled=%s\n", label);        /* We keep the cl_mgc_sem until mgc_fs_cleanup */        RETURN(0);err_ops:                fsfilt_put_ops(obd->obd_fsops);        obd->obd_fsops = NULL;        cli->cl_mgc_vfsmnt = NULL;        up(&cli->cl_mgc_sem);        RETURN(err);}static int mgc_fs_cleanup(struct obd_device *obd){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -