mgs_handler.c
来自「lustre 1.6.5 source code」· C语言 代码 · 共 773 行 · 第 1/2 页
C
773 行
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * lustre/mgs/mgs_handler.c * Lustre Management Server (mgs) request handler * * 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_MGS#define D_MGS 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_fsfilt.h>#include <lustre_commit_confd.h>#include <lustre_disk.h>#include "mgs_internal.h"/* Establish a connection to the MGS.*/static int mgs_connect(struct lustre_handle *conn, struct obd_device *obd, struct obd_uuid *cluuid, struct obd_connect_data *data, void *localdata){ struct obd_export *exp; int rc; ENTRY; if (!conn || !obd || !cluuid) RETURN(-EINVAL); rc = class_connect(conn, obd, cluuid); if (rc) RETURN(rc); exp = class_conn2export(conn); LASSERT(exp); mgs_counter_incr(exp, LPROC_MGS_CONNECT); if (data != NULL) { data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED; exp->exp_connect_flags = data->ocd_connect_flags; data->ocd_version = LUSTRE_VERSION_CODE; } rc = mgs_client_add(obd, exp); if (rc) { class_disconnect(exp); } else { class_export_put(exp); } RETURN(rc);}static int mgs_disconnect(struct obd_export *exp){ int rc; ENTRY; LASSERT(exp); class_export_get(exp); mgs_counter_incr(exp, LPROC_MGS_DISCONNECT); /* Disconnect early so that clients can't keep using export */ rc = class_disconnect(exp); ldlm_cancel_locks_for_export(exp); /* complete all outstanding replies */ spin_lock(&exp->exp_lock); while (!list_empty(&exp->exp_outstanding_replies)) { struct ptlrpc_reply_state *rs = list_entry(exp->exp_outstanding_replies.next, struct ptlrpc_reply_state, rs_exp_list); struct ptlrpc_service *svc = rs->rs_service; spin_lock(&svc->srv_lock); list_del_init(&rs->rs_exp_list); ptlrpc_schedule_difficult_reply(rs); spin_unlock(&svc->srv_lock); } spin_unlock(&exp->exp_lock); class_export_put(exp); RETURN(rc);}static int mgs_cleanup(struct obd_device *obd);static int mgs_handle(struct ptlrpc_request *req);/* Start the MGS obd */static int mgs_setup(struct obd_device *obd, obd_count len, void *buf){ struct lprocfs_static_vars lvars; struct mgs_obd *mgs = &obd->u.mgs; struct lustre_mount_info *lmi; struct lustre_sb_info *lsi; struct vfsmount *mnt; int rc = 0; ENTRY; CDEBUG(D_CONFIG, "Starting MGS\n"); /* Find our disk */ lmi = server_get_mount(obd->obd_name); if (!lmi) RETURN(rc = -EINVAL); mnt = lmi->lmi_mnt; lsi = s2lsi(lmi->lmi_sb); obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd)); if (IS_ERR(obd->obd_fsops)) GOTO(err_put, rc = PTR_ERR(obd->obd_fsops)); /* namespace for mgs llog */ obd->obd_namespace = ldlm_namespace_new("MGS", LDLM_NAMESPACE_SERVER, LDLM_NAMESPACE_MODEST); if (obd->obd_namespace == NULL) GOTO(err_ops, rc = -ENOMEM); /* ldlm setup */ ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL, "mgs_ldlm_client", &obd->obd_ldlm_client); LASSERT(!lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb))); rc = mgs_fs_setup(obd, mnt); if (rc) { CERROR("%s: MGS filesystem method init failed: rc = %d\n", obd->obd_name, rc); GOTO(err_ns, rc); } rc = llog_setup(obd, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL, &llog_lvfs_ops); if (rc) GOTO(err_fs, rc); /* No recovery for MGC's */ obd->obd_replayable = 0; /* Internal mgs setup */ mgs_init_fsdb_list(obd); sema_init(&mgs->mgs_sem, 1); /* Start the service threads */ mgs->mgs_service = ptlrpc_init_svc(MGS_NBUFS, MGS_BUFSIZE, MGS_MAXREQSIZE, MGS_MAXREPSIZE, MGS_REQUEST_PORTAL, MGC_REPLY_PORTAL, 2000, mgs_handle, LUSTRE_MGS_NAME, obd->obd_proc_entry, NULL, MGS_THREADS_AUTO_MIN, MGS_THREADS_AUTO_MAX, "ll_mgs"); if (!mgs->mgs_service) { CERROR("failed to start service\n"); GOTO(err_fs, rc = -ENOMEM); } rc = ptlrpc_start_threads(obd, mgs->mgs_service); if (rc) GOTO(err_thread, rc); /* Setup proc */ lprocfs_mgs_init_vars(&lvars); if (lprocfs_obd_setup(obd, lvars.obd_vars) == 0) { lproc_mgs_setup(obd); } ping_evictor_start(); LCONSOLE_INFO("MGS %s started\n", obd->obd_name); RETURN(0);err_thread: ptlrpc_unregister_service(mgs->mgs_service);err_fs: /* No extra cleanup needed for llog_init_commit_thread() */ mgs_fs_cleanup(obd);err_ns: ldlm_namespace_free(obd->obd_namespace, 0); obd->obd_namespace = NULL;err_ops: fsfilt_put_ops(obd->obd_fsops);err_put: server_put_mount(obd->obd_name, mnt); mgs->mgs_sb = 0; return rc;}static int mgs_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage){ int rc = 0; ENTRY; switch (stage) { case OBD_CLEANUP_EARLY: case OBD_CLEANUP_EXPORTS: break; case OBD_CLEANUP_SELF_EXP: llog_cleanup(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT)); rc = obd_llog_finish(obd, 0); break; case OBD_CLEANUP_OBD: break; } RETURN(rc);}static int mgs_ldlm_nsfree(void *data){ struct ldlm_namespace *ns = (struct ldlm_namespace *)data; int rc; ENTRY; ptlrpc_daemonize("ll_mgs_nsfree"); rc = ldlm_namespace_free(ns, 1 /* obd_force should always be on */); RETURN(rc);}static int mgs_cleanup(struct obd_device *obd){ struct mgs_obd *mgs = &obd->u.mgs; ENTRY; if (mgs->mgs_sb == NULL) RETURN(0); ping_evictor_stop(); ptlrpc_unregister_service(mgs->mgs_service); mgs_cleanup_fsdb_list(obd); lproc_mgs_cleanup(obd); mgs_fs_cleanup(obd); server_put_mount(obd->obd_name, mgs->mgs_vfsmnt); mgs->mgs_sb = NULL; /* Free the namespace in it's own thread, so that if the ldlm_cancel_handler put the last mgs obd ref, we won't deadlock here. */ cfs_kernel_thread(mgs_ldlm_nsfree, obd->obd_namespace, CLONE_VM | CLONE_FILES); fsfilt_put_ops(obd->obd_fsops); LCONSOLE_INFO("%s has stopped.\n", obd->obd_name); RETURN(0);}/* similar to filter_prepare_destroy */static int mgs_get_cfg_lock(struct obd_device *obd, char *fsname, struct lustre_handle *lockh){ struct ldlm_res_id res_id; int rc, flags = 0; ENTRY; rc = mgc_fsname2resid(fsname, &res_id); if (!rc) rc = ldlm_cli_enqueue_local(obd->obd_namespace, &res_id, LDLM_PLAIN, NULL, LCK_EX, &flags, ldlm_blocking_ast, ldlm_completion_ast, NULL, fsname, 0, NULL, lockh); if (rc) CERROR("can't take cfg lock for %s (%d)\n", fsname, rc); RETURN(rc);}static int mgs_put_cfg_lock(struct lustre_handle *lockh){ ENTRY; ldlm_lock_decref(lockh, LCK_EX); RETURN(0);}/* rc=0 means ok 1 means update <0 means error */static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti){ int rc; ENTRY; rc = mgs_check_index(obd, mti); if (rc == 0) { LCONSOLE_ERROR_MSG(0x13b, "%s claims to have registered, but " "this MGS does not know about it. Assuming " "writeconf.\n", mti->mti_svname); mti->mti_flags |= LDD_F_WRITECONF; rc = 1; } else if (rc == -1) { LCONSOLE_ERROR_MSG(0x13c, "Client log %s-client has " "disappeared! Regenerating all logs.\n", mti->mti_fsname); mti->mti_flags |= LDD_F_WRITECONF; rc = 1; } else { /* Index is correctly marked as used */ /* If the logs don't contain the mti_nids then add them as failover nids */ rc = mgs_check_failnid(obd, mti); } RETURN(rc);}/* Called whenever a target starts up. Flags indicate first connect, etc. */static int mgs_handle_target_reg(struct ptlrpc_request *req){ struct obd_device *obd = req->rq_export->exp_obd; struct lustre_handle lockh; struct mgs_target_info *mti, *rep_mti; int rep_size[] = { sizeof(struct ptlrpc_body), sizeof(*mti) }; int rc = 0, lockrc; ENTRY; mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_REG); mti = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*mti), lustre_swab_mgs_target_info); if (!(mti->mti_flags & (LDD_F_WRITECONF | LDD_F_UPGRADE14 | LDD_F_UPDATE))) { /* We're just here as a startup ping. */ CDEBUG(D_MGS, "Server %s is running on %s\n", mti->mti_svname, obd_export_nid2str(req->rq_export)); rc = mgs_check_target(obd, mti); /* above will set appropriate mti flags */ if (rc <= 0) /* Nothing wrong, or fatal error */ GOTO(out_nolock, rc); } /* Revoke the config lock to make sure nobody is reading. */ /* Although actually I think it should be alright if someone was reading while we were updating the logs - if we revoke at the end they will just update from where they left off. */ lockrc = mgs_get_cfg_lock(obd, mti->mti_fsname, &lockh); if (lockrc != ELDLM_OK) { LCONSOLE_ERROR_MSG(0x13d, "%s: Can't signal other nodes to " "update their configuration (%d). Updating " "local logs anyhow; you might have to " "manually restart other nodes to get the " "latest configuration.\n", obd->obd_name, lockrc); } OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_PAUSE_TARGET_REG, 10);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?