X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fmgs%2Fmgs_handler.c;h=1b5f2e01c7053dbab90db2bd696d5d0722de360c;hp=4c889687fd1cacb8d47552ab8cc21e597afd1d50;hb=f0c1b06f2418d2016e23eb6e8277be85ca13fc53;hpb=3e358040ae4b6fe8f28f20f8f1a07217d67d7e1a diff --git a/lustre/mgs/mgs_handler.c b/lustre/mgs/mgs_handler.c index 4c88968..1b5f2e0 100644 --- a/lustre/mgs/mgs_handler.c +++ b/lustre/mgs/mgs_handler.c @@ -27,7 +27,7 @@ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2011, 2012, Whamcloud, Inc. + * Copyright (c) 2010, 2013, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -36,410 +36,236 @@ * lustre/mgs/mgs_handler.c * * Author: Nathan Rutman + * Author: Alex Zhuravlev + * Author: Mikhail Pershin */ #define DEBUG_SUBSYSTEM S_MGS #define D_MGS D_CONFIG -#ifdef __KERNEL__ -# include -# include -# include -# include -#else -# include -#endif - #include -#include #include -#include -#include -#include "mgs_internal.h" #include -/* Establish a connection to the MGS.*/ -static int mgs_connect(const struct lu_env *env, - struct obd_export **exp, struct obd_device *obd, - struct obd_uuid *cluuid, struct obd_connect_data *data, - void *localdata) -{ - struct obd_export *lexp; - struct lustre_handle conn = { 0 }; - int rc; - ENTRY; - - if (!exp || !obd || !cluuid) - RETURN(-EINVAL); - - rc = class_connect(&conn, obd, cluuid); - if (rc) - RETURN(rc); +#include "mgs_internal.h" - lexp = class_conn2export(&conn); - LASSERT(lexp); +/* + * Regular MGS handlers + */ +static int mgs_connect(struct tgt_session_info *tsi) +{ + struct ptlrpc_request *req = tgt_ses_req(tsi); + int rc; - mgs_counter_incr(lexp, LPROC_MGS_CONNECT); + ENTRY; - if (data != NULL) { - data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED; - lexp->exp_connect_flags = data->ocd_connect_flags; - data->ocd_version = LUSTRE_VERSION_CODE; - } + rc = tgt_connect(tsi); + if (rc) + RETURN(rc); - rc = mgs_export_stats_init(obd, lexp, localdata); + if (lustre_msg_get_conn_cnt(req->rq_reqmsg) > 1) + lustre_msg_add_op_flags(req->rq_repmsg, MSG_CONNECT_RECONNECT); - if (rc) { - class_disconnect(lexp); - } else { - *exp = lexp; - } - - RETURN(rc); + RETURN(0); } -static int mgs_reconnect(const struct lu_env *env, - struct obd_export *exp, struct obd_device *obd, - struct obd_uuid *cluuid, struct obd_connect_data *data, - void *localdata) +static int mgs_disconnect(struct tgt_session_info *tsi) { - ENTRY; + int rc; - if (exp == NULL || obd == NULL || cluuid == NULL) - RETURN(-EINVAL); + ENTRY; - mgs_counter_incr(exp, LPROC_MGS_CONNECT); + LASSERT(tsi->tsi_exp); - if (data != NULL) { - data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED; - exp->exp_connect_flags = data->ocd_connect_flags; - data->ocd_version = LUSTRE_VERSION_CODE; - } - - RETURN(mgs_export_stats_init(obd, exp, localdata)); + rc = tgt_disconnect(tsi); + if (rc) + RETURN(err_serious(rc)); + RETURN(0); } -static int mgs_disconnect(struct obd_export *exp) +static int mgs_exception(struct tgt_session_info *tsi) { - int rc; - ENTRY; - - LASSERT(exp); - - mgs_fsc_cleanup(exp); + ENTRY; - class_export_get(exp); - mgs_counter_incr(exp, LPROC_MGS_DISCONNECT); + tgt_counter_incr(tsi->tsi_exp, LPROC_MGS_EXCEPTION); - rc = server_disconnect_export(exp); - class_export_put(exp); - RETURN(rc); + RETURN(0); } -static int mgs_cleanup(struct obd_device *obd); -static int mgs_handle(struct ptlrpc_request *req); - -static int mgs_llog_init(struct obd_device *obd, struct obd_llog_group *olg, - struct obd_device *tgt, int *index) +static int mgs_set_info(struct tgt_session_info *tsi) { - int rc; - ENTRY; - - LASSERT(olg == &obd->obd_olg); - rc = llog_setup(obd, olg, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL, - &llog_lvfs_ops); - RETURN(rc); + struct mgs_thread_info *mgi; + struct mgs_send_param *msp, *rep_msp; + struct lustre_cfg *lcfg; + int rc; + + ENTRY; + + mgi = mgs_env_info(tsi->tsi_env); + if (IS_ERR(mgi)) + RETURN(err_serious(PTR_ERR(mgi))); + + msp = req_capsule_client_get(tsi->tsi_pill, &RMF_MGS_SEND_PARAM); + if (msp == NULL) + RETURN(err_serious(-EFAULT)); + + /* Construct lustre_cfg structure to pass to function mgs_setparam */ + lustre_cfg_bufs_reset(&mgi->mgi_bufs, NULL); + lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, msp->mgs_param); + lcfg = lustre_cfg_new(LCFG_PARAM, &mgi->mgi_bufs); + + rc = mgs_setparam(tsi->tsi_env, exp2mgs_dev(tsi->tsi_exp), lcfg, + mgi->mgi_fsname); + if (rc) { + LCONSOLE_WARN("%s: Unable to set parameter %s for %s: %d\n", + tgt_name(tsi->tsi_tgt), msp->mgs_param, + mgi->mgi_fsname, rc); + GOTO(out_cfg, rc); + } + + /* send back the whole msp in the reply */ + rep_msp = req_capsule_server_get(tsi->tsi_pill, &RMF_MGS_SEND_PARAM); + *rep_msp = *msp; + EXIT; +out_cfg: + lustre_cfg_free(lcfg); + return rc; } -static int mgs_llog_finish(struct obd_device *obd, int count) -{ - struct llog_ctxt *ctxt; - int rc = 0; - ENTRY; - - ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT); - if (ctxt) - rc = llog_cleanup(ctxt); - - RETURN(rc); -} +enum ast_type { + AST_CONFIG = 1, + AST_PARAMS = 2, + AST_IR = 3 +}; -/* Start the MGS obd */ -static int mgs_setup(struct obd_device *obd, struct lustre_cfg *lcfg) +static int mgs_completion_ast_generic(struct ldlm_lock *lock, __u64 flags, + void *cbdata, enum ast_type type) { - static struct ptlrpc_service_conf conf; - 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(lsi->lsi_fstype); - if (IS_ERR(obd->obd_fsops)) - GOTO(err_put, rc = PTR_ERR(obd->obd_fsops)); - - if (lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb))) { - CERROR("%s: Underlying device is marked as read-only. " - "Setup failed\n", obd->obd_name); - GOTO(err_ops, rc = -EROFS); - } - - obd->u.obt.obt_magic = OBT_MAGIC; - obd->u.obt.obt_instance = 0; - - /* namespace for mgs llog */ - obd->obd_namespace = ldlm_namespace_new(obd ,"MGS", - LDLM_NAMESPACE_SERVER, - LDLM_NAMESPACE_MODEST, - LDLM_NS_TYPE_MGT); - 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); - - 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 = obd_llog_init(obd, &obd->obd_olg, obd, NULL); - if (rc) - GOTO(err_fs, rc); - - /* No recovery for MGC's */ - obd->obd_replayable = 0; - - /* Internal mgs setup */ - mgs_init_fsdb_list(obd); - cfs_mutex_init(&mgs->mgs_mutex); - mgs->mgs_start_time = cfs_time_current_sec(); - - /* Setup proc */ - lprocfs_mgs_init_vars(&lvars); - if (lprocfs_obd_setup(obd, lvars.obd_vars) == 0) { - lproc_mgs_setup(obd); - rc = lprocfs_alloc_md_stats(obd, LPROC_MGS_LAST); - if (rc) - GOTO(err_llog, rc); - } - - conf = (typeof(conf)) { - .psc_name = LUSTRE_MGS_NAME, - .psc_watchdog_factor = MGS_SERVICE_WATCHDOG_FACTOR, - .psc_buf = { - .bc_nbufs = MGS_NBUFS, - .bc_buf_size = MGS_BUFSIZE, - .bc_req_max_size = MGS_MAXREQSIZE, - .bc_rep_max_size = MGS_MAXREPSIZE, - .bc_req_portal = MGS_REQUEST_PORTAL, - .bc_rep_portal = MGC_REPLY_PORTAL, - }, - .psc_thr = { - .tc_thr_name = "ll_mgs", - .tc_nthrs_init = MGS_NTHRS_INIT, - .tc_nthrs_max = MGS_NTHRS_MAX, - .tc_ctx_tags = LCT_MD_THREAD, - }, - .psc_ops = { - .so_req_handler = mgs_handle, - .so_req_printer = target_print_req, - }, - }; - /* Start the service threads */ - mgs->mgs_service = ptlrpc_register_service(&conf, obd->obd_proc_entry); - if (IS_ERR(mgs->mgs_service)) { - rc = PTR_ERR(mgs->mgs_service); - CERROR("failed to start service: %d\n", rc); - GOTO(err_llog, rc); - } - - ping_evictor_start(); - - CDEBUG(D_INFO, "MGS %s started\n", obd->obd_name); - - RETURN(0); - -err_llog: - lproc_mgs_cleanup(obd); - obd_llog_finish(obd, 0); -err_fs: - /* No extra cleanup needed for llog_init_commit_thread() */ - mgs_fs_cleanup(obd); -err_ns: - ldlm_namespace_free(obd->obd_namespace, NULL, 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; + ENTRY; + + if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED | + LDLM_FL_BLOCK_CONV))) { + struct fs_db *fsdb; + + /* l_ast_data is used as a marker to avoid cancel ldlm lock + * twice. See LU-2317. */ + lock_res_and_lock(lock); + fsdb = (struct fs_db *)lock->l_ast_data; + lock->l_ast_data = NULL; + unlock_res_and_lock(lock); + + if (fsdb != NULL) { + struct lustre_handle lockh; + + switch(type) { + case AST_CONFIG: + /* clear the bit before lock put */ + clear_bit(FSDB_REVOKING_LOCK, + &fsdb->fsdb_flags); + break; + case AST_PARAMS: + clear_bit(FSDB_REVOKING_PARAMS, + &fsdb->fsdb_flags); + break; + case AST_IR: + mgs_ir_notify_complete(fsdb); + break; + default: + LBUG(); + } + + ldlm_lock2handle(lock, &lockh); + ldlm_lock_decref_and_cancel(&lockh, LCK_EX); + } + } + + RETURN(ldlm_completion_ast(lock, flags, cbdata)); } -static int mgs_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) +static int mgs_completion_ast_config(struct ldlm_lock *lock, __u64 flags, + void *cbdata) { - struct mgs_obd *mgs = &obd->u.mgs; - int rc = 0; - ENTRY; - - switch (stage) { - case OBD_CLEANUP_EARLY: - break; - case OBD_CLEANUP_EXPORTS: - ping_evictor_stop(); - ptlrpc_unregister_service(mgs->mgs_service); - mgs_cleanup_fsdb_list(obd); - rc = obd_llog_finish(obd, 0); - lproc_mgs_cleanup(obd); - break; - } - RETURN(rc); + return mgs_completion_ast_generic(lock, flags, cbdata, AST_CONFIG); } -/** - * Performs cleanup procedures for passed \a obd given it is mgs obd. - */ -static int mgs_cleanup(struct obd_device *obd) +static int mgs_completion_ast_params(struct ldlm_lock *lock, __u64 flags, + void *cbdata) { - struct mgs_obd *mgs = &obd->u.mgs; - ENTRY; - - if (mgs->mgs_sb == NULL) - RETURN(0); - - mgs_fs_cleanup(obd); - - server_put_mount(obd->obd_name, mgs->mgs_vfsmnt); - mgs->mgs_sb = NULL; - - ldlm_namespace_free(obd->obd_namespace, NULL, 1); - obd->obd_namespace = NULL; - - fsfilt_put_ops(obd->obd_fsops); - - LCONSOLE_INFO("%s has stopped.\n", obd->obd_name); - RETURN(0); + return mgs_completion_ast_generic(lock, flags, cbdata, AST_PARAMS); } -static int mgs_completion_ast_config(struct ldlm_lock *lock, int flags, - void *cbdata) +static int mgs_completion_ast_ir(struct ldlm_lock *lock, __u64 flags, + void *cbdata) { - ENTRY; - - if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED | - LDLM_FL_BLOCK_CONV))) { - struct fs_db *fsdb = (struct fs_db *)lock->l_ast_data; - struct lustre_handle lockh; - - /* clear the bit before lock put */ - cfs_clear_bit(FSDB_REVOKING_LOCK, &fsdb->fsdb_flags); - - ldlm_lock2handle(lock, &lockh); - ldlm_lock_decref_and_cancel(&lockh, LCK_EX); - } - - RETURN(ldlm_completion_ast(lock, flags, cbdata)); + return mgs_completion_ast_generic(lock, flags, cbdata, AST_IR); } -static int mgs_completion_ast_ir(struct ldlm_lock *lock, int flags, - void *cbdata) +void mgs_revoke_lock(struct mgs_device *mgs, struct fs_db *fsdb, int type) { - ENTRY; - - if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED | - LDLM_FL_BLOCK_CONV))) { - struct fs_db *fsdb; - - /* l_ast_data is used as a marker to avoid cancel ldlm lock - * twice. See LU-1259. */ - lock_res_and_lock(lock); - fsdb = (struct fs_db *)lock->l_ast_data; - lock->l_ast_data = NULL; - unlock_res_and_lock(lock); - - if (fsdb != NULL) { - struct lustre_handle lockh; - - mgs_ir_notify_complete(fsdb); - - ldlm_lock2handle(lock, &lockh); - ldlm_lock_decref_and_cancel(&lockh, LCK_EX); - } - } - - RETURN(ldlm_completion_ast(lock, flags, cbdata)); -} - -void mgs_revoke_lock(struct obd_device *obd, struct fs_db *fsdb, int type) -{ - ldlm_completion_callback cp = NULL; - struct lustre_handle lockh = { 0 }; - struct ldlm_res_id res_id; - int flags = LDLM_FL_ATOMIC_CB; - int rc; - ENTRY; - - LASSERT(fsdb->fsdb_name[0] != '\0'); - rc = mgc_fsname2resid(fsdb->fsdb_name, &res_id, type); - LASSERT(rc == 0); - - switch (type) { - case CONFIG_T_CONFIG: - cp = mgs_completion_ast_config; - if (cfs_test_and_set_bit(FSDB_REVOKING_LOCK, &fsdb->fsdb_flags)) - rc = -EALREADY; - break; - case CONFIG_T_RECOVER: - cp = mgs_completion_ast_ir; - default: - break; - } - - if (!rc) { - LASSERT(cp != NULL); - rc = ldlm_cli_enqueue_local(obd->obd_namespace, &res_id, - LDLM_PLAIN, NULL, LCK_EX, &flags, - ldlm_blocking_ast, cp, NULL, - fsdb, 0, NULL, &lockh); - if (rc != ELDLM_OK) { - CERROR("can't take cfg lock for "LPX64"/"LPX64"(%d)\n", - le64_to_cpu(res_id.name[0]), - le64_to_cpu(res_id.name[1]), rc); - - if (type == CONFIG_T_CONFIG) - cfs_clear_bit(FSDB_REVOKING_LOCK, - &fsdb->fsdb_flags); - } - /* lock has been cancelled in completion_ast. */ - } - - RETURN_EXIT; + ldlm_completion_callback cp = NULL; + struct lustre_handle lockh = { 0 }; + struct ldlm_res_id res_id; + __u64 flags = LDLM_FL_ATOMIC_CB; + int rc; + ENTRY; + + LASSERT(fsdb->fsdb_name[0] != '\0'); + rc = mgc_fsname2resid(fsdb->fsdb_name, &res_id, type); + LASSERT(rc == 0); + switch (type) { + case CONFIG_T_CONFIG: + cp = mgs_completion_ast_config; + if (test_and_set_bit(FSDB_REVOKING_LOCK, &fsdb->fsdb_flags)) + rc = -EALREADY; + break; + case CONFIG_T_PARAMS: + cp = mgs_completion_ast_params; + if (test_and_set_bit(FSDB_REVOKING_PARAMS, &fsdb->fsdb_flags)) + rc = -EALREADY; + break; + case CONFIG_T_RECOVER: + cp = mgs_completion_ast_ir; + default: + break; + } + + if (!rc) { + LASSERT(cp != NULL); + rc = ldlm_cli_enqueue_local(mgs->mgs_obd->obd_namespace, + &res_id, LDLM_PLAIN, NULL, LCK_EX, + &flags, ldlm_blocking_ast, cp, + NULL, fsdb, 0, LVB_T_NONE, NULL, + &lockh); + if (rc != ELDLM_OK) { + CERROR("can't take cfg lock for "LPX64"/"LPX64"(%d)\n", + le64_to_cpu(res_id.name[0]), + le64_to_cpu(res_id.name[1]), rc); + + if (type == CONFIG_T_CONFIG) + clear_bit(FSDB_REVOKING_LOCK, + &fsdb->fsdb_flags); + + if (type == CONFIG_T_PARAMS) + clear_bit(FSDB_REVOKING_PARAMS, + &fsdb->fsdb_flags); + } + /* lock has been cancelled in completion_ast. */ + } + + RETURN_EXIT; } /* rc=0 means ok 1 means update <0 means error */ -static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti) +static int mgs_check_target(const struct lu_env *env, + struct mgs_device *mgs, + struct mgs_target_info *mti) { int rc; ENTRY; - rc = mgs_check_index(obd, mti); + rc = mgs_check_index(env, mgs, mti); if (rc == 0) { LCONSOLE_ERROR_MSG(0x13b, "%s claims to have registered, but " "this MGS does not know about it, preventing " @@ -456,7 +282,7 @@ static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti) /* If the logs don't contain the mti_nids then add them as failover nids */ - rc = mgs_check_failnid(obd, mti); + rc = mgs_check_failnid(env, mgs, mti); } RETURN(rc); @@ -471,7 +297,7 @@ static int mgs_check_failover_reg(struct mgs_target_info *mti) ptr = mti->mti_params; while (class_find_param(ptr, PARAM_FAILNODE, &ptr) == 0) { - while (class_parse_nid(ptr, &nid, &ptr) == 0) { + while (class_parse_nid_quiet(ptr, &nid, &ptr) == 0) { for (i = 0; i < mti->mti_nid_count; i++) { if (nid == mti->mti_nids[i]) { LCONSOLE_WARN("Denying initial registra" @@ -487,24 +313,39 @@ static int mgs_check_failover_reg(struct mgs_target_info *mti) } /* Called whenever a target starts up. Flags indicate first connect, etc. */ -static int mgs_handle_target_reg(struct ptlrpc_request *req) +static int mgs_target_reg(struct tgt_session_info *tsi) { - struct obd_device *obd = req->rq_export->exp_obd; - struct mgs_target_info *mti, *rep_mti; - struct fs_db *fsdb; - int opc; - int rc = 0; - ENTRY; + struct obd_device *obd = tsi->tsi_exp->exp_obd; + struct mgs_device *mgs = exp2mgs_dev(tsi->tsi_exp); + struct mgs_target_info *mti, *rep_mti; + struct fs_db *fsdb; + int opc; + int rc = 0; + + ENTRY; - mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_REG); + rc = lu_env_refill((struct lu_env *)tsi->tsi_env); + if (rc) + return err_serious(rc); - mti = req_capsule_client_get(&req->rq_pill, &RMF_MGS_TARGET_INFO); + tgt_counter_incr(tsi->tsi_exp, LPROC_MGS_TARGET_REG); + + mti = req_capsule_client_get(tsi->tsi_pill, &RMF_MGS_TARGET_INFO); + if (mti == NULL) { + DEBUG_REQ(D_HA, tgt_ses_req(tsi), "no mgs_send_param"); + RETURN(err_serious(-EFAULT)); + } + + if (OCD_HAS_FLAG(&tgt_ses_req(tsi)->rq_export->exp_connect_data, + IMP_RECOV)) + opc = mti->mti_flags & LDD_F_OPC_MASK; + else + opc = LDD_F_OPC_REG; - opc = mti->mti_flags & LDD_F_OPC_MASK; if (opc == LDD_F_OPC_READY) { CDEBUG(D_MGS, "fs: %s index: %d is ready to reconnect.\n", mti->mti_fsname, mti->mti_stripe_index); - rc = mgs_ir_update(obd, mti); + rc = mgs_ir_update(tsi->tsi_env, mgs, mti); if (rc) { LASSERT(!(mti->mti_flags & LDD_F_IR_CAPABLE)); CERROR("Update IR return with %d(ignore and IR " @@ -527,16 +368,16 @@ static int mgs_handle_target_reg(struct ptlrpc_request *req) 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); + mti->mti_svname, obd_export_nid2str(tsi->tsi_exp)); + rc = mgs_check_target(tsi->tsi_env, mgs, mti); /* above will set appropriate mti flags */ if (rc <= 0) /* Nothing wrong, or fatal error */ GOTO(out_nolock, rc); - } else { - if (!(mti->mti_flags & LDD_F_NO_PRIMNODE) - && (rc = mgs_check_failover_reg(mti))) - GOTO(out_nolock, rc); + } else if (!(mti->mti_flags & LDD_F_NO_PRIMNODE)) { + rc = mgs_check_failover_reg(mti); + if (rc) + GOTO(out_nolock, rc); } OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_PAUSE_TARGET_REG, 10); @@ -544,14 +385,15 @@ static int mgs_handle_target_reg(struct ptlrpc_request *req) if (mti->mti_flags & LDD_F_WRITECONF) { if (mti->mti_flags & LDD_F_SV_TYPE_MDT && mti->mti_stripe_index == 0) { - rc = mgs_erase_logs(obd, mti->mti_fsname); + rc = mgs_erase_logs(tsi->tsi_env, mgs, + mti->mti_fsname); LCONSOLE_WARN("%s: Logs for fs %s were removed by user " "request. All servers must be restarted " "in order to regenerate the logs." "\n", obd->obd_name, mti->mti_fsname); } else if (mti->mti_flags & (LDD_F_SV_TYPE_OST | LDD_F_SV_TYPE_MDT)) { - rc = mgs_erase_log(obd, mti->mti_svname); + rc = mgs_erase_log(tsi->tsi_env, mgs, mti->mti_svname); LCONSOLE_WARN("%s: Regenerating %s log by user " "request.\n", obd->obd_name, mti->mti_svname); @@ -559,9 +401,11 @@ static int mgs_handle_target_reg(struct ptlrpc_request *req) mti->mti_flags |= LDD_F_UPDATE; /* Erased logs means start from scratch. */ mti->mti_flags &= ~LDD_F_UPGRADE14; + if (rc) + GOTO(out_nolock, rc); } - rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb); + rc = mgs_find_or_make_fsdb(tsi->tsi_env, mgs, mti->mti_fsname, &fsdb); if (rc) { CERROR("Can't get db for %s: %d\n", mti->mti_fsname, rc); GOTO(out_nolock, rc); @@ -575,18 +419,10 @@ static int mgs_handle_target_reg(struct ptlrpc_request *req) * from where they left off. */ - /* COMPAT_146 */ if (mti->mti_flags & LDD_F_UPGRADE14) { - rc = mgs_upgrade_sv_14(obd, mti, fsdb); - if (rc) { - CERROR("Can't upgrade from 1.4 (%d)\n", rc); - GOTO(out, rc); - } - - /* We're good to go */ - mti->mti_flags |= LDD_F_UPDATE; - } - /* end COMPAT_146 */ + CERROR("Can't upgrade from 1.4 (%d)\n", rc); + GOTO(out, rc); + } if (mti->mti_flags & LDD_F_UPDATE) { CDEBUG(D_MGS, "updating %s, index=%d\n", mti->mti_svname, @@ -594,7 +430,7 @@ static int mgs_handle_target_reg(struct ptlrpc_request *req) /* create or update the target log and update the client/mdt logs */ - rc = mgs_write_log_target(obd, mti, fsdb); + rc = mgs_write_log_target(tsi->tsi_env, mgs, mti, fsdb); if (rc) { CERROR("Failed to write %s log (%d)\n", mti->mti_svname, rc); @@ -608,358 +444,140 @@ static int mgs_handle_target_reg(struct ptlrpc_request *req) } out: - mgs_revoke_lock(obd, fsdb, CONFIG_T_CONFIG); + mgs_revoke_lock(mgs, fsdb, CONFIG_T_CONFIG); out_nolock: - CDEBUG(D_MGS, "replying with %s, index=%d, rc=%d\n", mti->mti_svname, - mti->mti_stripe_index, rc); - req->rq_status = rc; - if (rc) - /* we need an error flag to tell the target what's going on, - * instead of just doing it by error code only. */ - mti->mti_flags |= LDD_F_ERROR; - - rc = req_capsule_server_pack(&req->rq_pill); - if (rc) - RETURN(rc); - - /* send back the whole mti in the reply */ - rep_mti = req_capsule_server_get(&req->rq_pill, &RMF_MGS_TARGET_INFO); - *rep_mti = *mti; - - /* Flush logs to disk */ - fsfilt_sync(obd, obd->u.mgs.mgs_sb); - RETURN(rc); -} - -static int mgs_set_info_rpc(struct ptlrpc_request *req) -{ - struct obd_device *obd = req->rq_export->exp_obd; - struct mgs_send_param *msp, *rep_msp; - int rc; - struct lustre_cfg_bufs bufs; - struct lustre_cfg *lcfg; - char fsname[MTI_NAME_MAXLEN]; - ENTRY; - - msp = req_capsule_client_get(&req->rq_pill, &RMF_MGS_SEND_PARAM); - LASSERT(msp); - - /* Construct lustre_cfg structure to pass to function mgs_setparam */ - lustre_cfg_bufs_reset(&bufs, NULL); - lustre_cfg_bufs_set_string(&bufs, 1, msp->mgs_param); - lcfg = lustre_cfg_new(LCFG_PARAM, &bufs); - rc = mgs_setparam(obd, lcfg, fsname); - if (rc) { - CERROR("Error %d in setting the parameter %s for fs %s\n", - rc, msp->mgs_param, fsname); - RETURN(rc); - } - - lustre_cfg_free(lcfg); - - rc = req_capsule_server_pack(&req->rq_pill); - if (rc == 0) { - rep_msp = req_capsule_server_get(&req->rq_pill, &RMF_MGS_SEND_PARAM); - rep_msp = msp; - } - RETURN(rc); -} - -static int mgs_config_read(struct ptlrpc_request *req) -{ - struct mgs_config_body *body; - int rc; - ENTRY; - - body = req_capsule_client_get(&req->rq_pill, &RMF_MGS_CONFIG_BODY); - if (body == NULL) - RETURN(-EINVAL); - - switch (body->mcb_type) { - case CONFIG_T_RECOVER: - rc = mgs_get_ir_logs(req); - break; - - case CONFIG_T_CONFIG: - rc = -ENOTSUPP; - break; - - default: - rc = -EINVAL; - break; - } - - RETURN(rc); -} - -/* - * similar as in ost_connect_check_sptlrpc() - */ -static int mgs_connect_check_sptlrpc(struct ptlrpc_request *req) -{ - struct obd_export *exp = req->rq_export; - struct obd_device *obd = exp->exp_obd; - struct fs_db *fsdb; - struct sptlrpc_flavor flvr; - int rc = 0; - - if (exp->exp_flvr.sf_rpc == SPTLRPC_FLVR_INVALID) { - rc = mgs_find_or_make_fsdb(obd, MGSSELF_NAME, &fsdb); - if (rc) - return rc; - - cfs_mutex_lock(&fsdb->fsdb_mutex); - if (sptlrpc_rule_set_choose(&fsdb->fsdb_srpc_gen, - LUSTRE_SP_MGC, LUSTRE_SP_MGS, - req->rq_peer.nid, - &flvr) == 0) { - /* by defualt allow any flavors */ - flvr.sf_rpc = SPTLRPC_FLVR_ANY; - } - cfs_mutex_unlock(&fsdb->fsdb_mutex); - - cfs_spin_lock(&exp->exp_lock); - - exp->exp_sp_peer = req->rq_sp_from; - exp->exp_flvr = flvr; - - if (exp->exp_flvr.sf_rpc != SPTLRPC_FLVR_ANY && - exp->exp_flvr.sf_rpc != req->rq_flvr.sf_rpc) { - CERROR("invalid rpc flavor %x, expect %x, from %s\n", - req->rq_flvr.sf_rpc, exp->exp_flvr.sf_rpc, - libcfs_nid2str(req->rq_peer.nid)); - rc = -EACCES; - } - - cfs_spin_unlock(&exp->exp_lock); - } else { - if (exp->exp_sp_peer != req->rq_sp_from) { - CERROR("RPC source %s doesn't match %s\n", - sptlrpc_part2name(req->rq_sp_from), - sptlrpc_part2name(exp->exp_sp_peer)); - rc = -EACCES; - } else { - rc = sptlrpc_target_export_check(exp, req); - } - } - - return rc; + CDEBUG(D_MGS, "replying with %s, index=%d, rc=%d\n", mti->mti_svname, + mti->mti_stripe_index, rc); + /* An error flag is set in the mti reply rather than an error code */ + if (rc) + mti->mti_flags |= LDD_F_ERROR; + + /* send back the whole mti in the reply */ + rep_mti = req_capsule_server_get(tsi->tsi_pill, &RMF_MGS_TARGET_INFO); + *rep_mti = *mti; + + /* Flush logs to disk */ + dt_sync(tsi->tsi_env, mgs->mgs_bottom); + RETURN(rc); } /* Called whenever a target cleans up. */ -/* XXX - Currently unused */ -static int mgs_handle_target_del(struct ptlrpc_request *req) -{ - ENTRY; - mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_DEL); - RETURN(0); -} - -/* XXX - Currently unused */ -static int mgs_handle_exception(struct ptlrpc_request *req) +static int mgs_target_del(struct tgt_session_info *tsi) { - ENTRY; - mgs_counter_incr(req->rq_export, LPROC_MGS_EXCEPTION); - RETURN(0); -} - -/* - * For old clients there is no direct way of knowing which filesystems - * a client is operating at the MGS side. But we need to pick up those - * clients so that the MGS can mark the corresponding filesystem as - * non-IR capable because old clients are not ready to be notified. - * - * This is why we have this _hack_ function. We detect the filesystem's - * name by hacking llog operation which is currently used by the clients - * to fetch configuration logs. At present this is fine because this is - * the ONLY llog operation between mgc and the MGS. - * - * If extra llog operation is going to be added, this function needs fixing. - * - * If releases prior than 2.0 are not supported, we can remove this function. - */ -static int mgs_handle_fslog_hack(struct ptlrpc_request *req) -{ - char *logname; - char fsname[16]; - char *ptr; - int rc; - - /* XXX: We suppose that llog at mgs is only used for - * fetching file system log */ - logname = req_capsule_client_get(&req->rq_pill, &RMF_NAME); - if (logname == NULL) { - CERROR("No logname, is llog on MGS used for something else?\n"); - return -EINVAL; - } - - ptr = strchr(logname, '-'); - rc = (int)(ptr - logname); - if (ptr == NULL || rc >= sizeof(fsname)) { - CERROR("Invalid logname received: %s\n", logname); - return -EINVAL; - } + ENTRY; - strncpy(fsname, logname, rc); - fsname[rc] = 0; - rc = mgs_fsc_attach(req->rq_export, fsname); - if (rc < 0 && rc != -EEXIST) - CERROR("add fs client %s returns %d\n", fsname, rc); + tgt_counter_incr(tsi->tsi_exp, LPROC_MGS_TARGET_DEL); - return rc; + RETURN(0); } -/* TODO: handle requests in a similar way as MDT: see mdt_handle_common() */ -int mgs_handle(struct ptlrpc_request *req) +static int mgs_config_read(struct tgt_session_info *tsi) { - int fail = OBD_FAIL_MGS_ALL_REPLY_NET; - int opc, rc = 0; - ENTRY; - - req_capsule_init(&req->rq_pill, req, RCL_SERVER); - CFS_FAIL_TIMEOUT_MS(OBD_FAIL_MGS_PAUSE_REQ, cfs_fail_val); - if (CFS_FAIL_CHECK(OBD_FAIL_MGS_ALL_REQUEST_NET)) - RETURN(0); + struct ptlrpc_request *req = tgt_ses_req(tsi); + struct mgs_config_body *body; + int rc; - LASSERT(current->journal_info == NULL); - opc = lustre_msg_get_opc(req->rq_reqmsg); + ENTRY; - if (opc == SEC_CTX_INIT || - opc == SEC_CTX_INIT_CONT || - opc == SEC_CTX_FINI) - GOTO(out, rc = 0); + body = req_capsule_client_get(tsi->tsi_pill, &RMF_MGS_CONFIG_BODY); + if (body == NULL) { + DEBUG_REQ(D_HA, req, "no mgs_config_body"); + RETURN(err_serious(-EFAULT)); + } - if (opc != MGS_CONNECT) { - if (!class_connected_export(req->rq_export)) { - DEBUG_REQ(D_MGS, req, "operation on unconnected MGS\n"); - req->rq_status = -ENOTCONN; - GOTO(out, rc = -ENOTCONN); - } - } - - switch (opc) { - case MGS_CONNECT: - DEBUG_REQ(D_MGS, req, "connect"); - /* MGS and MDS have same request format for connect */ - req_capsule_set(&req->rq_pill, &RQF_MDS_CONNECT); - rc = target_handle_connect(req); - if (rc == 0) - rc = mgs_connect_check_sptlrpc(req); - - if (!rc && (lustre_msg_get_conn_cnt(req->rq_reqmsg) > 1)) - /* Make clients trying to reconnect after a MGS restart - happy; also requires obd_replayable */ - lustre_msg_add_op_flags(req->rq_repmsg, - MSG_CONNECT_RECONNECT); - break; - case MGS_DISCONNECT: - DEBUG_REQ(D_MGS, req, "disconnect"); - /* MGS and MDS have same request format for disconnect */ - req_capsule_set(&req->rq_pill, &RQF_MDS_DISCONNECT); - rc = target_handle_disconnect(req); - req->rq_status = rc; /* superfluous? */ - break; - case MGS_EXCEPTION: - DEBUG_REQ(D_MGS, req, "exception"); - rc = mgs_handle_exception(req); - break; - case MGS_TARGET_REG: - DEBUG_REQ(D_MGS, req, "target add"); - req_capsule_set(&req->rq_pill, &RQF_MGS_TARGET_REG); - rc = mgs_handle_target_reg(req); - break; - case MGS_TARGET_DEL: - DEBUG_REQ(D_MGS, req, "target del"); - rc = mgs_handle_target_del(req); - break; - case MGS_SET_INFO: - DEBUG_REQ(D_MGS, req, "set_info"); - req_capsule_set(&req->rq_pill, &RQF_MGS_SET_INFO); - rc = mgs_set_info_rpc(req); - break; - case MGS_CONFIG_READ: - DEBUG_REQ(D_MGS, req, "read config"); - req_capsule_set(&req->rq_pill, &RQF_MGS_CONFIG_READ); - rc = mgs_config_read(req); - break; - case LDLM_ENQUEUE: - DEBUG_REQ(D_MGS, req, "enqueue"); - req_capsule_set(&req->rq_pill, &RQF_LDLM_ENQUEUE); - rc = ldlm_handle_enqueue(req, ldlm_server_completion_ast, - ldlm_server_blocking_ast, NULL); - break; - case LDLM_BL_CALLBACK: - case LDLM_CP_CALLBACK: - DEBUG_REQ(D_MGS, req, "callback"); - CERROR("callbacks should not happen on MGS\n"); - LBUG(); - break; - - case OBD_PING: - DEBUG_REQ(D_INFO, req, "ping"); - req_capsule_set(&req->rq_pill, &RQF_OBD_PING); - rc = target_handle_ping(req); - break; - case OBD_LOG_CANCEL: - DEBUG_REQ(D_MGS, req, "log cancel"); - rc = -ENOTSUPP; /* la la la */ - break; - - case LLOG_ORIGIN_HANDLE_CREATE: - DEBUG_REQ(D_MGS, req, "llog_init"); - req_capsule_set(&req->rq_pill, &RQF_LLOG_ORIGIN_HANDLE_CREATE); - rc = llog_origin_handle_create(req); - if (rc == 0) - (void)mgs_handle_fslog_hack(req); - break; - case LLOG_ORIGIN_HANDLE_NEXT_BLOCK: - DEBUG_REQ(D_MGS, req, "llog next block"); - req_capsule_set(&req->rq_pill, - &RQF_LLOG_ORIGIN_HANDLE_NEXT_BLOCK); - rc = llog_origin_handle_next_block(req); - break; - case LLOG_ORIGIN_HANDLE_READ_HEADER: - DEBUG_REQ(D_MGS, req, "llog read header"); - req_capsule_set(&req->rq_pill, - &RQF_LLOG_ORIGIN_HANDLE_READ_HEADER); - rc = llog_origin_handle_read_header(req); - break; - case LLOG_ORIGIN_HANDLE_CLOSE: - DEBUG_REQ(D_MGS, req, "llog close"); - rc = llog_origin_handle_close(req); - break; - case LLOG_CATINFO: - DEBUG_REQ(D_MGS, req, "llog catinfo"); + switch (body->mcb_type) { + case CONFIG_T_RECOVER: + rc = mgs_get_ir_logs(req); + break; + case CONFIG_T_CONFIG: rc = -EOPNOTSUPP; break; - default: - req->rq_status = -ENOTSUPP; - rc = ptlrpc_error(req); - RETURN(rc); - } - - LASSERT(current->journal_info == NULL); + default: + rc = -EINVAL; + break; + } - if (rc) - CERROR("MGS handle cmd=%d rc=%d\n", opc, rc); + RETURN(rc); +} -out: - target_send_reply(req, rc, fail); - RETURN(0); +static int mgs_llog_open(struct tgt_session_info *tsi) +{ + struct mgs_thread_info *mgi; + struct ptlrpc_request *req = tgt_ses_req(tsi); + char *logname; + int rc; + + ENTRY; + + rc = tgt_llog_open(tsi); + if (rc) + RETURN(rc); + + /* + * For old clients there is no direct way of knowing which file system + * a client is operating at the MGS side. But we need to pick up those + * clients so that the MGS can mark the corresponding file system as + * non-IR capable because old clients are not ready to be notified. + * + * Therefore we attempt to detect the file systems name by hacking the + * llog operation which is currently used by the clients to fetch + * configuration logs. At present this is fine because this is the + * ONLY llog operation between mgc and the MGS. + * + * If extra llog operation are going to be added, this function needs + * further work. + * + * When releases prior than 2.0 are not supported, the following code + * can be removed. + */ + mgi = mgs_env_info(tsi->tsi_env); + if (IS_ERR(mgi)) + RETURN(PTR_ERR(mgi)); + + logname = req_capsule_client_get(tsi->tsi_pill, &RMF_NAME); + if (logname) { + char *ptr = strchr(logname, '-'); + int len = (int)(ptr - logname); + + if (ptr == NULL || len >= sizeof(mgi->mgi_fsname)) { + LCONSOLE_WARN("%s: non-config logname received: %s\n", + tgt_name(tsi->tsi_tgt), logname); + /* not error, this can be llog test name */ + } else { + strncpy(mgi->mgi_fsname, logname, len); + mgi->mgi_fsname[len] = 0; + + rc = mgs_fsc_attach(tsi->tsi_env, tsi->tsi_exp, + mgi->mgi_fsname); + if (rc && rc != -EEXIST) { + LCONSOLE_WARN("%s: Unable to add client %s " + "to file system %s: %d\n", + tgt_name(tsi->tsi_tgt), + libcfs_nid2str(req->rq_peer.nid), + mgi->mgi_fsname, rc); + } else { + rc = 0; + } + } + } else { + CERROR("%s: no logname in request\n", tgt_name(tsi->tsi_tgt)); + RETURN(-EINVAL); + } + RETURN(rc); } static inline int mgs_init_export(struct obd_export *exp) { - struct mgs_export_data *data = &exp->u.eu_mgs_data; + struct mgs_export_data *data = &exp->u.eu_mgs_data; - /* init mgs_export_data for fsc */ - cfs_spin_lock_init(&data->med_lock); - CFS_INIT_LIST_HEAD(&data->med_clients); + /* init mgs_export_data for fsc */ + spin_lock_init(&data->med_lock); + CFS_INIT_LIST_HEAD(&data->med_clients); - cfs_spin_lock(&exp->exp_lock); - exp->exp_connecting = 1; - cfs_spin_unlock(&exp->exp_lock); + spin_lock(&exp->exp_lock); + exp->exp_connecting = 1; + spin_unlock(&exp->exp_lock); /* self-export doesn't need client data and ldlm initialization */ if (unlikely(obd_uuid_equals(&exp->exp_obd->obd_uuid, @@ -1002,106 +620,84 @@ static int mgs_extract_fs_pool(char * arg, char *fsname, char *poolname) RETURN(0); } -static int mgs_iocontrol_pool(struct obd_device *obd, +static int mgs_iocontrol_pool(const struct lu_env *env, + struct mgs_device *mgs, struct obd_ioctl_data *data) { + struct mgs_thread_info *mgi = mgs_env_info(env); int rc; struct lustre_cfg *lcfg = NULL; - struct llog_rec_hdr rec; - char *fsname = NULL; char *poolname = NULL; ENTRY; - OBD_ALLOC(fsname, MTI_NAME_MAXLEN); - if (fsname == NULL) - RETURN(-ENOMEM); - OBD_ALLOC(poolname, LOV_MAXPOOLNAME + 1); - if (poolname == NULL) { - rc = -ENOMEM; - GOTO(out_pool, rc); - } - rec.lrh_len = llog_data_len(data->ioc_plen1); + if (poolname == NULL) + RETURN(-ENOMEM); - if (data->ioc_type == LUSTRE_CFG_TYPE) { - rec.lrh_type = OBD_CFG_REC; - } else { - CERROR("unknown cfg record type:%d \n", data->ioc_type); - rc = -EINVAL; - GOTO(out_pool, rc); + if (data->ioc_type != LUSTRE_CFG_TYPE) { + CERROR("%s: unknown cfg record type: %d\n", + mgs->mgs_obd->obd_name, data->ioc_type); + GOTO(out_pool, rc = -EINVAL); } - if (data->ioc_plen1 > CFS_PAGE_SIZE) { - rc = -E2BIG; - GOTO(out_pool, rc); - } + if (data->ioc_plen1 > PAGE_CACHE_SIZE) + GOTO(out_pool, rc = -E2BIG); OBD_ALLOC(lcfg, data->ioc_plen1); if (lcfg == NULL) GOTO(out_pool, rc = -ENOMEM); - if (cfs_copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1)) - GOTO(out_pool, rc = -EFAULT); + if (copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1)) + GOTO(out_lcfg, rc = -EFAULT); - if (lcfg->lcfg_bufcount < 2) { - GOTO(out_pool, rc = -EFAULT); - } + if (lcfg->lcfg_bufcount < 2) + GOTO(out_lcfg, rc = -EFAULT); /* first arg is always . */ - mgs_extract_fs_pool(lustre_cfg_string(lcfg, 1), fsname, - poolname); + rc = mgs_extract_fs_pool(lustre_cfg_string(lcfg, 1), mgi->mgi_fsname, + poolname); + if (rc) + GOTO(out_lcfg, rc); switch (lcfg->lcfg_command) { - case LCFG_POOL_NEW: { + case LCFG_POOL_NEW: if (lcfg->lcfg_bufcount != 2) - RETURN(-EINVAL); - rc = mgs_pool_cmd(obd, LCFG_POOL_NEW, fsname, + GOTO(out_lcfg, rc = -EINVAL); + rc = mgs_pool_cmd(env, mgs, LCFG_POOL_NEW, mgi->mgi_fsname, poolname, NULL); break; - } - case LCFG_POOL_ADD: { + case LCFG_POOL_ADD: if (lcfg->lcfg_bufcount != 3) - RETURN(-EINVAL); - rc = mgs_pool_cmd(obd, LCFG_POOL_ADD, fsname, poolname, - lustre_cfg_string(lcfg, 2)); + GOTO(out_lcfg, rc = -EINVAL); + rc = mgs_pool_cmd(env, mgs, LCFG_POOL_ADD, mgi->mgi_fsname, + poolname, lustre_cfg_string(lcfg, 2)); break; - } - case LCFG_POOL_REM: { + case LCFG_POOL_REM: if (lcfg->lcfg_bufcount != 3) - RETURN(-EINVAL); - rc = mgs_pool_cmd(obd, LCFG_POOL_REM, fsname, poolname, - lustre_cfg_string(lcfg, 2)); + GOTO(out_lcfg, rc = -EINVAL); + rc = mgs_pool_cmd(env, mgs, LCFG_POOL_REM, mgi->mgi_fsname, + poolname, lustre_cfg_string(lcfg, 2)); break; - } - case LCFG_POOL_DEL: { + case LCFG_POOL_DEL: if (lcfg->lcfg_bufcount != 2) - RETURN(-EINVAL); - rc = mgs_pool_cmd(obd, LCFG_POOL_DEL, fsname, + GOTO(out_lcfg, rc = -EINVAL); + rc = mgs_pool_cmd(env, mgs, LCFG_POOL_DEL, mgi->mgi_fsname, poolname, NULL); break; - } - default: { + default: rc = -EINVAL; - GOTO(out_pool, rc); - } } if (rc) { CERROR("OBD_IOC_POOL err %d, cmd %X for pool %s.%s\n", - rc, lcfg->lcfg_command, fsname, poolname); - GOTO(out_pool, rc); + rc, lcfg->lcfg_command, mgi->mgi_fsname, poolname); + GOTO(out_lcfg, rc); } +out_lcfg: + OBD_FREE(lcfg, data->ioc_plen1); out_pool: - if (lcfg != NULL) - OBD_FREE(lcfg, data->ioc_plen1); - - if (fsname != NULL) - OBD_FREE(fsname, MTI_NAME_MAXLEN); - - if (poolname != NULL) - OBD_FREE(poolname, LOV_MAXPOOLNAME + 1); - + OBD_FREE(poolname, LOV_MAXPOOLNAME + 1); RETURN(rc); } @@ -1109,115 +705,686 @@ out_pool: int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len, void *karg, void *uarg) { - struct obd_device *obd = exp->exp_obd; + struct mgs_device *mgs = exp2mgs_dev(exp); struct obd_ioctl_data *data = karg; - struct lvfs_run_ctxt saved; + struct lu_env env; int rc = 0; ENTRY; CDEBUG(D_IOCTL, "handling ioctl cmd %#x\n", cmd); + rc = lu_env_init(&env, LCT_MG_THREAD); + if (rc) + RETURN(rc); + switch (cmd) { case OBD_IOC_PARAM: { + struct mgs_thread_info *mgi = mgs_env_info(&env); struct lustre_cfg *lcfg; - struct llog_rec_hdr rec; - char fsname[MTI_NAME_MAXLEN]; - rec.lrh_len = llog_data_len(data->ioc_plen1); - - if (data->ioc_type == LUSTRE_CFG_TYPE) { - rec.lrh_type = OBD_CFG_REC; - } else { - CERROR("unknown cfg record type:%d \n", data->ioc_type); - RETURN(-EINVAL); + if (data->ioc_type != LUSTRE_CFG_TYPE) { + CERROR("%s: unknown cfg record type: %d\n", + mgs->mgs_obd->obd_name, data->ioc_type); + GOTO(out, rc = -EINVAL); } OBD_ALLOC(lcfg, data->ioc_plen1); if (lcfg == NULL) - RETURN(-ENOMEM); - if (cfs_copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1)) + GOTO(out, rc = -ENOMEM); + if (copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1)) GOTO(out_free, rc = -EFAULT); if (lcfg->lcfg_bufcount < 1) GOTO(out_free, rc = -EINVAL); - rc = mgs_setparam(obd, lcfg, fsname); - if (rc) { - CERROR("setparam err %d\n", rc); - GOTO(out_free, rc); - } + rc = mgs_setparam(&env, mgs, lcfg, mgi->mgi_fsname); + if (rc) + CERROR("%s: setparam err: rc = %d\n", + exp->exp_obd->obd_name, rc); out_free: OBD_FREE(lcfg, data->ioc_plen1); - RETURN(rc); + break; } - case OBD_IOC_POOL: { - RETURN(mgs_iocontrol_pool(obd, data)); - } + case OBD_IOC_REPLACE_NIDS: { + if (!data->ioc_inllen1 || !data->ioc_inlbuf1) { + CERROR("No device name specified!\n"); + rc = -EINVAL; + break; + } + + if (data->ioc_inlbuf1[data->ioc_inllen1 - 1] != 0) { + CERROR("Device name is not NUL terminated!\n"); + rc = -EINVAL; + break; + } + + if (data->ioc_plen1 > MTI_NAME_MAXLEN) { + CERROR("Device name is too long\n"); + rc = -EOVERFLOW; + break; + } + + if (!data->ioc_inllen2 || !data->ioc_inlbuf2) { + CERROR("No NIDs were specified!\n"); + rc = -EINVAL; + break; + } + + if (data->ioc_inlbuf2[data->ioc_inllen2 - 1] != 0) { + CERROR("NID list is not NUL terminated!\n"); + rc = -EINVAL; + break; + } + + /* replace nids in llog */ + rc = mgs_replace_nids(&env, mgs, data->ioc_inlbuf1, + data->ioc_inlbuf2); + if (rc) + CERROR("%s: error replacing nids: rc = %d\n", + exp->exp_obd->obd_name, rc); + + break; + } + + case OBD_IOC_POOL: + rc = mgs_iocontrol_pool(&env, mgs, data); + break; case OBD_IOC_DUMP_LOG: { struct llog_ctxt *ctxt; - ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT); - push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL); - pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); + + ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT); + rc = class_config_dump_llog(&env, ctxt, data->ioc_inlbuf1, + NULL); llog_ctxt_put(ctxt); - RETURN(rc); + break; } + case OBD_IOC_LLOG_CANCEL: + case OBD_IOC_LLOG_REMOVE: case OBD_IOC_LLOG_CHECK: case OBD_IOC_LLOG_INFO: case OBD_IOC_LLOG_PRINT: { struct llog_ctxt *ctxt; - ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT); - push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL); - rc = llog_ioctl(ctxt, cmd, data); - pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL); - llog_ctxt_put(ctxt); - - RETURN(rc); + ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT); + rc = llog_ioctl(&env, ctxt, cmd, data); + llog_ctxt_put(ctxt); + break; } default: - CDEBUG(D_INFO, "unknown command %x\n", cmd); - RETURN(-EINVAL); + CERROR("%s: unknown command %#x\n", + mgs->mgs_obd->obd_name, cmd); + rc = -ENOTTY; + break; } - RETURN(0); +out: + lu_env_fini(&env); + RETURN(rc); +} + +static int mgs_connect_to_osd(struct mgs_device *m, const char *nextdev) +{ + struct obd_connect_data *data = NULL; + struct obd_device *obd; + int rc; + ENTRY; + + OBD_ALLOC_PTR(data); + if (data == NULL) + RETURN(-ENOMEM); + + obd = class_name2obd(nextdev); + if (obd == NULL) { + CERROR("can't locate next device: %s\n", nextdev); + GOTO(out, rc = -ENOTCONN); + } + + data->ocd_version = LUSTRE_VERSION_CODE; + + rc = obd_connect(NULL, &m->mgs_bottom_exp, obd, + &obd->obd_uuid, data, NULL); + if (rc) { + CERROR("cannot connect to next dev %s (%d)\n", nextdev, rc); + GOTO(out, rc); + } + + m->mgs_bottom = lu2dt_dev(m->mgs_bottom_exp->exp_obd->obd_lu_dev); + m->mgs_dt_dev.dd_lu_dev.ld_site = m->mgs_bottom->dd_lu_dev.ld_site; + LASSERT(m->mgs_dt_dev.dd_lu_dev.ld_site); +out: + OBD_FREE_PTR(data); + RETURN(rc); +} + +static struct tgt_handler mgs_mgs_handlers[] = { +TGT_RPC_HANDLER(MGS_FIRST_OPC, + 0, MGS_CONNECT, mgs_connect, + &RQF_CONNECT, LUSTRE_OBD_VERSION), +TGT_RPC_HANDLER(MGS_FIRST_OPC, + 0, MGS_DISCONNECT, mgs_disconnect, + &RQF_MDS_DISCONNECT, LUSTRE_OBD_VERSION), +TGT_MGS_HDL_VAR(0, MGS_EXCEPTION, mgs_exception), +TGT_MGS_HDL (HABEO_REFERO | MUTABOR, MGS_SET_INFO, mgs_set_info), +TGT_MGS_HDL (HABEO_REFERO | MUTABOR, MGS_TARGET_REG, mgs_target_reg), +TGT_MGS_HDL_VAR(0, MGS_TARGET_DEL, mgs_target_del), +TGT_MGS_HDL (HABEO_REFERO, MGS_CONFIG_READ, mgs_config_read), +}; + +static struct tgt_handler mgs_obd_handlers[] = { +TGT_OBD_HDL(0, OBD_PING, tgt_obd_ping), +}; + +static struct tgt_handler mgs_dlm_handlers[] = { +[LDLM_ENQUEUE - LDLM_FIRST_OPC] = { + .th_name = "LDLM_ENQUEUE", + /* don't use th_fail_id for MGS to don't interfere with MDS tests. + * * There are no tests for MGS with OBD_FAIL_LDLM_ENQUEUE_NET so it + * * is safe. If such tests will be needed we have to distinguish + * * MDS and MGS fail ids, e.g use OBD_FAIL_MGS_ENQUEUE_NET for MGS + * * instead of common OBD_FAIL_LDLM_ENQUEUE_NET */ + .th_fail_id = 0, + .th_opc = LDLM_ENQUEUE, + .th_flags = HABEO_CLAVIS, + .th_act = tgt_enqueue, + .th_fmt = &RQF_LDLM_ENQUEUE, + .th_version = LUSTRE_DLM_VERSION, + }, +}; + +static struct tgt_handler mgs_llog_handlers[] = { +TGT_LLOG_HDL (0, LLOG_ORIGIN_HANDLE_CREATE, mgs_llog_open), +TGT_LLOG_HDL (0, LLOG_ORIGIN_HANDLE_NEXT_BLOCK, tgt_llog_next_block), +TGT_LLOG_HDL (0, LLOG_ORIGIN_HANDLE_READ_HEADER, tgt_llog_read_header), +TGT_LLOG_HDL_VAR(0, LLOG_ORIGIN_HANDLE_CLOSE, tgt_llog_close), +TGT_LLOG_HDL (0, LLOG_ORIGIN_HANDLE_PREV_BLOCK, tgt_llog_prev_block), +}; + +static struct tgt_opc_slice mgs_common_slice[] = { + { + .tos_opc_start = MGS_FIRST_OPC, + .tos_opc_end = MGS_LAST_OPC, + .tos_hs = mgs_mgs_handlers + }, + { + .tos_opc_start = OBD_FIRST_OPC, + .tos_opc_end = OBD_LAST_OPC, + .tos_hs = mgs_obd_handlers + }, + { + .tos_opc_start = LDLM_FIRST_OPC, + .tos_opc_end = LDLM_LAST_OPC, + .tos_hs = mgs_dlm_handlers + }, + { + .tos_opc_start = LLOG_FIRST_OPC, + .tos_opc_end = LLOG_LAST_OPC, + .tos_hs = mgs_llog_handlers + }, + { + .tos_opc_start = SEC_FIRST_OPC, + .tos_opc_end = SEC_LAST_OPC, + .tos_hs = tgt_sec_ctx_handlers + }, + { + .tos_hs = NULL + } +}; + +static int mgs_init0(const struct lu_env *env, struct mgs_device *mgs, + struct lu_device_type *ldt, struct lustre_cfg *lcfg) +{ + struct ptlrpc_service_conf conf; + struct obd_device *obd; + struct lustre_mount_info *lmi; + struct llog_ctxt *ctxt; + int rc; + + ENTRY; + + lmi = server_get_mount(lustre_cfg_string(lcfg, 0)); + if (lmi == NULL) + RETURN(-ENODEV); + + mgs->mgs_dt_dev.dd_lu_dev.ld_ops = &mgs_lu_ops; + + rc = mgs_connect_to_osd(mgs, lustre_cfg_string(lcfg, 3)); + if (rc) + GOTO(err_lmi, rc); + + obd = class_name2obd(lustre_cfg_string(lcfg, 0)); + LASSERT(obd); + mgs->mgs_obd = obd; + mgs->mgs_obd->obd_lu_dev = &mgs->mgs_dt_dev.dd_lu_dev; + + obd->u.obt.obt_magic = OBT_MAGIC; + obd->u.obt.obt_instance = 0; + + /* namespace for mgs llog */ + obd->obd_namespace = ldlm_namespace_new(obd ,"MGS", + LDLM_NAMESPACE_SERVER, + LDLM_NAMESPACE_MODEST, + LDLM_NS_TYPE_MGT); + if (obd->obd_namespace == NULL) + GOTO(err_ops, rc = -ENOMEM); + + /* No recovery for MGCs */ + obd->obd_replayable = 0; + + rc = tgt_init(env, &mgs->mgs_lut, obd, mgs->mgs_bottom, + mgs_common_slice, OBD_FAIL_MGS_ALL_REQUEST_NET, + OBD_FAIL_MGS_ALL_REPLY_NET); + if (rc) + GOTO(err_ns, rc); + + rc = mgs_fs_setup(env, mgs); + if (rc) { + CERROR("%s: MGS filesystem method init failed: rc = %d\n", + obd->obd_name, rc); + GOTO(err_tgt, rc); + } + + rc = llog_setup(env, obd, &obd->obd_olg, LLOG_CONFIG_ORIG_CTXT, + obd, &llog_osd_ops); + if (rc) + GOTO(err_fs, rc); + + /* XXX: we need this trick till N:1 stack is supported + * set "current" directory for named llogs */ + ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT); + LASSERT(ctxt); + ctxt->loc_dir = mgs->mgs_configs_dir; + llog_ctxt_put(ctxt); + + /* Internal mgs setup */ + mgs_init_fsdb_list(mgs); + mutex_init(&mgs->mgs_mutex); + mgs->mgs_start_time = cfs_time_current_sec(); + spin_lock_init(&mgs->mgs_lock); + + rc = lproc_mgs_setup(mgs, lustre_cfg_string(lcfg, 3)); + if (rc != 0) { + CERROR("%s: cannot initialize proc entry: rc = %d\n", + obd->obd_name, rc); + GOTO(err_llog, rc); + } + + ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL, + "mgs_ldlm_client", &obd->obd_ldlm_client); + + conf = (typeof(conf)) { + .psc_name = LUSTRE_MGS_NAME, + .psc_watchdog_factor = MGS_SERVICE_WATCHDOG_FACTOR, + .psc_buf = { + .bc_nbufs = MGS_NBUFS, + .bc_buf_size = MGS_BUFSIZE, + .bc_req_max_size = MGS_MAXREQSIZE, + .bc_rep_max_size = MGS_MAXREPSIZE, + .bc_req_portal = MGS_REQUEST_PORTAL, + .bc_rep_portal = MGC_REPLY_PORTAL, + }, + .psc_thr = { + .tc_thr_name = "ll_mgs", + .tc_nthrs_init = MGS_NTHRS_INIT, + .tc_nthrs_max = MGS_NTHRS_MAX, + .tc_ctx_tags = LCT_MG_THREAD, + }, + .psc_ops = { + .so_req_handler = tgt_request_handle, + .so_req_printer = target_print_req, + }, + }; + + /* Start the service threads */ + mgs->mgs_service = ptlrpc_register_service(&conf, obd->obd_proc_entry); + if (IS_ERR(mgs->mgs_service)) { + rc = PTR_ERR(mgs->mgs_service); + CERROR("failed to start mgs service: %d\n", rc); + mgs->mgs_service = NULL; + GOTO(err_lproc, rc); + } + + ping_evictor_start(); + + CDEBUG(D_INFO, "MGS %s started\n", obd->obd_name); + + /* device stack is not yet fully setup to keep no objects behind */ + lu_site_purge(env, mgs2lu_dev(mgs)->ld_site, ~0); + RETURN(0); +err_lproc: + lproc_mgs_cleanup(mgs); +err_llog: + ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT); + if (ctxt) { + ctxt->loc_dir = NULL; + llog_cleanup(env, ctxt); + } +err_tgt: + tgt_fini(env, &mgs->mgs_lut); +err_fs: + /* No extra cleanup needed for llog_init_commit_thread() */ + mgs_fs_cleanup(env, mgs); +err_ns: + ldlm_namespace_free(obd->obd_namespace, NULL, 0); + obd->obd_namespace = NULL; +err_ops: + lu_site_purge(env, mgs2lu_dev(mgs)->ld_site, ~0); + if (!cfs_hash_is_empty(mgs2lu_dev(mgs)->ld_site->ls_obj_hash)) { + LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, D_ERROR, NULL); + lu_site_print(env, mgs2lu_dev(mgs)->ld_site, &msgdata, + lu_cdebug_printer); + } + obd_disconnect(mgs->mgs_bottom_exp); +err_lmi: + if (lmi) + server_put_mount(lustre_cfg_string(lcfg, 0), lmi->lmi_mnt); + RETURN(rc); +} + +static struct lu_device *mgs_device_free(const struct lu_env *env, + struct lu_device *lu) +{ + struct mgs_device *mgs = lu2mgs_dev(lu); + ENTRY; + + dt_device_fini(&mgs->mgs_dt_dev); + OBD_FREE_PTR(mgs); + RETURN(NULL); +} + +static int mgs_process_config(const struct lu_env *env, + struct lu_device *dev, + struct lustre_cfg *lcfg) +{ + LBUG(); + return 0; +} + +static int mgs_object_init(const struct lu_env *env, struct lu_object *o, + const struct lu_object_conf *unused) +{ + struct mgs_device *d = lu2mgs_dev(o->lo_dev); + struct lu_device *under; + struct lu_object *below; + int rc = 0; + ENTRY; + + /* do no set .do_ops as mgs calls to bottom osd directly */ + + CDEBUG(D_INFO, "object init, fid = "DFID"\n", + PFID(lu_object_fid(o))); + + under = &d->mgs_bottom->dd_lu_dev; + below = under->ld_ops->ldo_object_alloc(env, o->lo_header, under); + if (below != NULL) + lu_object_add(o, below); + else + rc = -ENOMEM; + + return 0; +} + +static void mgs_object_free(const struct lu_env *env, struct lu_object *o) +{ + struct mgs_object *obj = lu2mgs_obj(o); + struct lu_object_header *h = o->lo_header; + + dt_object_fini(&obj->mgo_obj); + lu_object_header_fini(h); + OBD_FREE_PTR(obj); +} + +static int mgs_object_print(const struct lu_env *env, void *cookie, + lu_printer_t p, const struct lu_object *l) +{ + const struct mgs_object *o = lu2mgs_obj((struct lu_object *) l); + + return (*p)(env, cookie, LUSTRE_MGS_NAME"-object@%p", o); +} + +struct lu_object_operations mgs_lu_obj_ops = { + .loo_object_init = mgs_object_init, + .loo_object_free = mgs_object_free, + .loo_object_print = mgs_object_print, +}; + +struct lu_object *mgs_object_alloc(const struct lu_env *env, + const struct lu_object_header *hdr, + struct lu_device *d) +{ + struct lu_object_header *h; + struct mgs_object *o; + struct lu_object *l; + + LASSERT(hdr == NULL); + + OBD_ALLOC_PTR(o); + if (o != NULL) { + l = &o->mgo_obj.do_lu; + h = &o->mgo_header; + + lu_object_header_init(h); + dt_object_init(&o->mgo_obj, h, d); + lu_object_add_top(h, l); + + l->lo_ops = &mgs_lu_obj_ops; + + return l; + } else { + return NULL; + } +} + +const struct lu_device_operations mgs_lu_ops = { + .ldo_object_alloc = mgs_object_alloc, + .ldo_process_config = mgs_process_config, +}; + +static struct lu_device *mgs_device_alloc(const struct lu_env *env, + struct lu_device_type *type, + struct lustre_cfg *lcfg) +{ + struct mgs_device *mgs; + struct lu_device *ludev; + + OBD_ALLOC_PTR(mgs); + if (mgs == NULL) { + ludev = ERR_PTR(-ENOMEM); + } else { + int rc; + + ludev = mgs2lu_dev(mgs); + dt_device_init(&mgs->mgs_dt_dev, type); + rc = mgs_init0(env, mgs, type, lcfg); + if (rc != 0) { + mgs_device_free(env, ludev); + ludev = ERR_PTR(rc); + } + } + return ludev; +} + +static struct lu_device *mgs_device_fini(const struct lu_env *env, + struct lu_device *d) +{ + struct mgs_device *mgs = lu2mgs_dev(d); + struct obd_device *obd = mgs->mgs_obd; + struct llog_ctxt *ctxt; + + ENTRY; + + LASSERT(mgs->mgs_bottom); + + class_disconnect_exports(obd); + + ping_evictor_stop(); + + ptlrpc_unregister_service(mgs->mgs_service); + + obd_exports_barrier(obd); + obd_zombie_barrier(); + + tgt_fini(env, &mgs->mgs_lut); + mgs_cleanup_fsdb_list(mgs); + lproc_mgs_cleanup(mgs); + + ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT); + if (ctxt) { + ctxt->loc_dir = NULL; + llog_cleanup(env, ctxt); + } + + mgs_fs_cleanup(env, mgs); + + ldlm_namespace_free(obd->obd_namespace, NULL, 1); + obd->obd_namespace = NULL; + + lu_site_purge(env, d->ld_site, ~0); + if (!cfs_hash_is_empty(d->ld_site->ls_obj_hash)) { + LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, D_ERROR, NULL); + lu_site_print(env, d->ld_site, &msgdata, lu_cdebug_printer); + } + + LASSERT(mgs->mgs_bottom_exp); + obd_disconnect(mgs->mgs_bottom_exp); + + server_put_mount(obd->obd_name, NULL); + + RETURN(NULL); +} + +/* context key constructor/destructor: mgs_key_init, mgs_key_fini */ +LU_KEY_INIT_FINI(mgs, struct mgs_thread_info); + +LU_TYPE_INIT_FINI(mgs, &mgs_thread_key); + +LU_CONTEXT_KEY_DEFINE(mgs, LCT_MG_THREAD); + +static struct lu_device_type_operations mgs_device_type_ops = { + .ldto_init = mgs_type_init, + .ldto_fini = mgs_type_fini, + + .ldto_start = mgs_type_start, + .ldto_stop = mgs_type_stop, + + .ldto_device_alloc = mgs_device_alloc, + .ldto_device_free = mgs_device_free, + + .ldto_device_fini = mgs_device_fini +}; + +static struct lu_device_type mgs_device_type = { + .ldt_tags = LU_DEVICE_DT, + .ldt_name = LUSTRE_MGS_NAME, + .ldt_ops = &mgs_device_type_ops, + .ldt_ctx_tags = LCT_MG_THREAD +}; + +static int mgs_obd_connect(const struct lu_env *env, struct obd_export **exp, + struct obd_device *obd, struct obd_uuid *cluuid, + struct obd_connect_data *data, void *localdata) +{ + struct obd_export *lexp; + struct lustre_handle conn = { 0 }; + int rc; + + ENTRY; + + if (exp == NULL || obd == NULL || cluuid == NULL) + RETURN(-EINVAL); + + rc = class_connect(&conn, obd, cluuid); + if (rc) + RETURN(rc); + + lexp = class_conn2export(&conn); + if (lexp == NULL) + RETURN(-EFAULT); + + if (data != NULL) { + data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED; + data->ocd_version = LUSTRE_VERSION_CODE; + lexp->exp_connect_data = *data; + } + + tgt_counter_incr(lexp, LPROC_MGS_CONNECT); + + rc = mgs_export_stats_init(obd, lexp, localdata); + if (rc) + class_disconnect(lexp); + else + *exp = lexp; + + RETURN(rc); +} + +static int mgs_obd_reconnect(const struct lu_env *env, struct obd_export *exp, + struct obd_device *obd, struct obd_uuid *cluuid, + struct obd_connect_data *data, void *localdata) +{ + ENTRY; + + if (exp == NULL || obd == NULL || cluuid == NULL) + RETURN(-EINVAL); + + tgt_counter_incr(exp, LPROC_MGS_CONNECT); + + if (data != NULL) { + data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED; + data->ocd_version = LUSTRE_VERSION_CODE; + exp->exp_connect_data = *data; + } + + RETURN(mgs_export_stats_init(obd, exp, localdata)); +} + +static int mgs_obd_disconnect(struct obd_export *exp) +{ + int rc; + + ENTRY; + + LASSERT(exp); + + mgs_fsc_cleanup(exp); + + class_export_get(exp); + tgt_counter_incr(exp, LPROC_MGS_DISCONNECT); + + rc = server_disconnect_export(exp); + class_export_put(exp); + RETURN(rc); } /* use obd ops to offer management infrastructure */ -static struct obd_ops mgs_obd_ops = { - .o_owner = THIS_MODULE, - .o_connect = mgs_connect, - .o_reconnect = mgs_reconnect, - .o_disconnect = mgs_disconnect, - .o_setup = mgs_setup, - .o_precleanup = mgs_precleanup, - .o_cleanup = mgs_cleanup, - .o_init_export = mgs_init_export, - .o_destroy_export = mgs_destroy_export, - .o_iocontrol = mgs_iocontrol, - .o_llog_init = mgs_llog_init, - .o_llog_finish = mgs_llog_finish +static struct obd_ops mgs_obd_device_ops = { + .o_owner = THIS_MODULE, + .o_connect = mgs_obd_connect, + .o_reconnect = mgs_obd_reconnect, + .o_disconnect = mgs_obd_disconnect, + .o_init_export = mgs_init_export, + .o_destroy_export = mgs_destroy_export, + .o_iocontrol = mgs_iocontrol, }; static int __init mgs_init(void) { - struct lprocfs_static_vars lvars; + struct lprocfs_static_vars lvars; - lprocfs_mgs_init_vars(&lvars); - class_register_type(&mgs_obd_ops, NULL, - lvars.module_vars, LUSTRE_MGS_NAME, NULL); + lprocfs_mgs_init_vars(&lvars); + class_register_type(&mgs_obd_device_ops, NULL, lvars.module_vars, + LUSTRE_MGS_NAME, &mgs_device_type); - return 0; + return 0; } static void /*__exit*/ mgs_exit(void) { - class_unregister_type(LUSTRE_MGS_NAME); + class_unregister_type(LUSTRE_MGS_NAME); } MODULE_AUTHOR("Sun Microsystems, Inc. ");