#include <linux/lprocfs_status.h>
#include <linux/lustre_fsfilt.h>
#include <linux/lustre_commit_confd.h>
+#include <linux/lustre_disk.h>
#include "mgs_internal.h"
-static int mgs_postsetup(struct obd_device *obd);
static int mgs_cleanup(struct obd_device *obd);
/* Establish a connection to the MGS.*/
struct obd_uuid *cluuid, struct obd_connect_data *data)
{
struct obd_export *exp;
- struct mgs_export_data *med;
- struct mgs_client_data *mcd;
- int rc, abort_recovery;
+ int rc;
ENTRY;
if (!conn || !obd || !cluuid)
RETURN(-EINVAL);
- /* Check for aborted recovery. */
- spin_lock_bh(&obd->obd_processing_task_lock);
- abort_recovery = obd->obd_abort_recovery;
- spin_unlock_bh(&obd->obd_processing_task_lock);
- if (abort_recovery)
- target_abort_recovery(obd);
-
rc = class_connect(conn, obd, cluuid);
if (rc)
RETURN(rc);
exp = class_conn2export(conn);
LASSERT(exp);
- med = &exp->exp_mgs_data;
if (data != NULL) {
- data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED;
+ data->ocd_connect_flags &= MGMT_CONNECT_SUPPORTED;
exp->exp_connect_flags = data->ocd_connect_flags;
}
- OBD_ALLOC(mcd, sizeof(*mcd));
- if (!mcd) {
- CERROR("mgs: out of memory for client data\n");
- GOTO(out, rc = -ENOMEM);
- }
-
- memcpy(mcd->mcd_uuid, cluuid, sizeof(mcd->mcd_uuid));
- med->med_mcd = mcd;
-
-out:
if (rc) {
- if (mcd) {
- OBD_FREE(mcd, sizeof(*mcd));
- med->med_mcd = NULL;
- }
class_disconnect(exp);
} else {
class_export_put(exp);
RETURN(rc);
}
-static int mgs_init_export(struct obd_export *exp)
-{
- struct mgs_export_data *med = &exp->exp_mgs_data;
-
- INIT_LIST_HEAD(&med->med_open_head);
- spin_lock_init(&med->med_open_lock);
- RETURN(0);
-}
-
static int mgs_disconnect(struct obd_export *exp)
{
unsigned long irqflags;
/* 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_irqsave(&exp->exp_lock, irqflags);
RETURN(rc);
}
-/* mount the file system (secretly) */
+/* Start the MGS obd */
static int mgs_setup(struct obd_device *obd, obd_count len, void *buf)
{
struct lprocfs_static_vars lvars;
- struct lustre_cfg* lcfg = buf;
- char *options = NULL;
+ char *ns_name = "MGS";
struct mgs_obd *mgs = &obd->u.mgs;
+ struct lustre_mount_info *lmi;
+ struct lustre_sb_info *lsi;
struct vfsmount *mnt;
- unsigned long page;
int rc = 0;
ENTRY;
- /* setup 1:/dev/loop/0 2:ext3 3:mgs 4:errors=remount-ro,iopen_nopriv*/
-
- if (lcfg->lcfg_bufcount < 3)
- RETURN(rc = -EINVAL);
+ CDEBUG(D_CONFIG, "Starting MGS\n");
- if (LUSTRE_CFG_BUFLEN(lcfg, 1) == 0 || LUSTRE_CFG_BUFLEN(lcfg, 2) == 0)
+ lmi = server_get_mount(obd->obd_name);
+ if (!lmi)
RETURN(rc = -EINVAL);
- obd->obd_fsops = fsfilt_get_ops(lustre_cfg_string(lcfg, 2));
+ 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))
- RETURN(rc = PTR_ERR(obd->obd_fsops));
-
- page = __get_free_page(GFP_KERNEL);
- if (!page)
- RETURN(-ENOMEM);
-
- options = (char *)page;
- memset(options, 0, PAGE_SIZE);
-
- if (LUSTRE_CFG_BUFLEN(lcfg, 4) > 0 && lustre_cfg_buf(lcfg, 4))
- sprintf(options , ",%s", lustre_cfg_string(lcfg, 4));
-
- //FIXME mount was already done in lustre_fill_super,
- //we just need to access it
- mnt = do_kern_mount(lustre_cfg_string(lcfg, 2), 0,
- lustre_cfg_string(lcfg, 1), (void *)options);
- free_page(page);
- if (IS_ERR(mnt)) {
- rc = PTR_ERR(mnt);
- CERROR("do_kern_mount failed: rc = %d\n", rc);
- GOTO(err_ops, rc);
- }
+ GOTO(err_put, rc = PTR_ERR(obd->obd_fsops));
- CDEBUG(D_SUPER, "%s: mnt = %p\n", lustre_cfg_string(lcfg, 1), mnt);
+ /* namespace for mgs llog */
+ obd->obd_namespace = ldlm_namespace_new(ns_name, LDLM_NAMESPACE_SERVER);
+ if (obd->obd_namespace == NULL) {
+ mgs_cleanup(obd);
+ GOTO(err_ops, rc = -ENOMEM);
+ }
LASSERT(!lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb)));
if (rc) {
CERROR("%s: MGS filesystem method init failed: rc = %d\n",
obd->obd_name, rc);
- GOTO(err_put, rc);
+ GOTO(err_ns, rc);
}
- INIT_LIST_HEAD(&mgs->mgs_open_llogs);
-
rc = llog_start_commit_thread();
if (rc < 0)
GOTO(err_fs, rc);
-#if 0
- //FIXME: no LDLM support for llog now
- ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
- "mgs_ldlm_client", &obd->obd_ldlm_client);
-#endif
- obd->obd_replayable = 1;
- rc = mgs_postsetup(obd);
+ rc = llog_setup(obd, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
+ &llog_lvfs_ops);
if (rc)
GOTO(err_fs, rc);
+ mgs_init_db_list(obd);
+
lprocfs_init_vars(mgs, &lvars);
lprocfs_obd_setup(obd, lvars.obd_vars);
- if (obd->obd_recovering) {
- LCONSOLE_WARN("MGT %s now serving %s, but will be in recovery "
- "until %d %s reconnect, or if no clients "
- "reconnect for %d:%.02d; during that time new "
- "clients will not be allowed to connect. "
- "Recovery progress can be monitored by watching "
- "/proc/fs/lustre/mgs/%s/recovery_status.\n",
- obd->obd_name,
- lustre_cfg_string(lcfg, 1),
- obd->obd_recoverable_clients,
- (obd->obd_recoverable_clients == 1)
- ? "client" : "clients",
- (int)(OBD_RECOVERY_TIMEOUT / HZ) / 60,
- (int)(OBD_RECOVERY_TIMEOUT / HZ) % 60,
- obd->obd_name);
- } else {
- LCONSOLE_INFO("MGT %s now serving %s with recovery %s.\n",
- obd->obd_name,
- lustre_cfg_string(lcfg, 1),
- obd->obd_replayable ? "enabled" : "disabled");
- }
-//FIXME: no ldlm support now
+ LCONSOLE_INFO("MGS %s started\n", obd->obd_name);
+
ldlm_timeout = 6;
ping_evictor_start();
err_fs:
/* No extra cleanup needed for llog_init_commit_thread() */
mgs_fs_cleanup(obd);
-err_put:
- unlock_kernel();
- mntput(mgs->mgs_vfsmnt);
- mgs->mgs_sb = 0;
- lock_kernel();
+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, mgs->mgs_vfsmnt);
+ mgs->mgs_sb = 0;
return rc;
}
-static int mgs_postsetup(struct obd_device *obd)
-{
- int rc = 0;
- ENTRY;
-
- rc = llog_setup(obd, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
- &llog_lvfs_ops);
- RETURN(rc);
-}
-
static int mgs_precleanup(struct obd_device *obd, int stage)
{
int rc = 0;
ENTRY;
- llog_cleanup(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT));
- rc = obd_llog_finish(obd, 0);
+ switch (stage) {
+ case OBD_CLEANUP_SELF_EXP:
+ mgs_cleanup_db_list(obd);
+ llog_cleanup(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT));
+ rc = obd_llog_finish(obd, 0);
+ }
RETURN(rc);
}
{
struct mgs_obd *mgs = &obd->u.mgs;
lvfs_sbdev_type save_dev;
- int must_relock = 0;
ENTRY;
ping_evictor_stop();
RETURN(0);
save_dev = lvfs_sbdev(mgs->mgs_sb);
- lprocfs_obd_cleanup(obd);
-
- mgs_update_server_data(obd, 1);
-
- mgs_fs_cleanup(obd);
+// lprocfs_obd_cleanup(obd);
- if (atomic_read(&obd->u.mgs.mgs_vfsmnt->mnt_count) > 2)
- CERROR("%s: mount busy, mnt_count %d != 2\n", obd->obd_name,
- atomic_read(&obd->u.mgs.mgs_vfsmnt->mnt_count));
+ // mgs_update_server_data(obd, 1);
- /* We can only unlock kernel if we are in the context of sys_ioctl,
- otherwise we never called lock_kernel */
- if (kernel_locked()) {
- unlock_kernel();
- must_relock++;
- }
+ //mgs_fs_cleanup(obd);
- mntput(mgs->mgs_vfsmnt);
+ server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
mgs->mgs_sb = NULL;
+ ldlm_namespace_free(obd->obd_namespace, obd->obd_force);
+
spin_lock_bh(&obd->obd_processing_task_lock);
if (obd->obd_recovering) {
target_cancel_recovery_timer(obd);
lvfs_clear_rdonly(save_dev);
- if (must_relock)
- lock_kernel();
-
fsfilt_put_ops(obd->obd_fsops);
- LCONSOLE_INFO("MDT %s has stopped.\n", obd->obd_name);
+ LCONSOLE_INFO("MGS %s has stopped.\n", obd->obd_name);
RETURN(0);
}
-/* Look up an entry by inode number. */
-/* this function ONLY returns valid dget'd dentries with an initialized inode
- or errors */
-struct dentry *mgs_fid2dentry(struct mgs_obd *mgs, struct ll_fid *fid,
- struct vfsmount **mnt)
-{
- unsigned long ino = fid->id;
- __u32 generation = fid->generation;
- struct mgs_open_llog *mollog, *n;
- struct list_head *llog_list = &mgs->mgs_open_llogs;
- struct inode *inode;
- struct dentry *result = NULL;
-
- if (ino == 0)
- RETURN(ERR_PTR(-ESTALE));
-
-
- CDEBUG(D_DENTRY, "--> mgs_fid2dentry: ino/gen %lu/%u, sb %p\n",
- ino, generation, mgs->mgs_sb);
-
- list_for_each_entry_safe(mollog, n, llog_list, mol_list) {
- if (mollog->mol_id == ino) {
- result = mollog->mol_dentry;
- dget(result);
- }
- }
-
- if (!result)
- RETURN(NULL);
-
- inode = result->d_inode;
- if (!inode)
- RETURN(ERR_PTR(-ENOENT));
-
- if (generation && inode->i_generation != generation) {
- /* we didn't find the right inode.. */
- CERROR("bad inode %lu, link: %lu ct: %d or generation %u/%u\n",
- inode->i_ino, (unsigned long)inode->i_nlink,
- atomic_read(&inode->i_count), inode->i_generation,
- generation);
- dput(result);
- RETURN(ERR_PTR(-ENOENT));
- }
-
- if (mnt) {
- *mnt = mgs->mgs_vfsmnt;
- mntget(*mnt);
- }
-
- RETURN(result);
-}
-
-static struct dentry *mgs_lvfs_fid2dentry(__u64 id, __u32 gen, __u64 gr,
- void *data)
-{
- struct obd_device *obd = data;
- struct ll_fid fid;
- fid.id = id;
- fid.generation = gen;
- return mgs_fid2dentry(&obd->u.mgs, &fid, NULL);
-}
+static int mgs_handle_target_add(struct ptlrpc_request *req)
+{
+ struct obd_device *obd = req->rq_export->exp_obd;
+ struct mgmt_target_info *req_mti, *mti, *rep_mti;
+ int rep_size = sizeof(*mti);
+ int rc;
+ ENTRY;
-static int mgs_lvfs_open_llog(__u64 id, struct dentry *dentry , void *data)
-{
- struct obd_device *obd = data;
- struct mgs_obd *mgs = &obd->u.mgs;
- struct mgs_open_llog *mollog, *n;
- struct list_head *llog_list = &mgs->mgs_open_llogs;
-
- list_for_each_entry_safe(mollog, n, llog_list, mol_list) {
- if (mollog->mol_id == id) {
- dget(dentry);
- return 0;
+ OBD_ALLOC(mti, sizeof(*mti));
+ if (!mti)
+ GOTO(out, rc = -ENOMEM);
+ req_mti = lustre_swab_reqbuf(req, 0, sizeof(*mti),
+ lustre_swab_mgmt_target_info);
+ memcpy(mti, req_mti, sizeof(*mti));
+
+ /* set the new target index if needed */
+ if (mti->mti_flags & LDD_F_NEED_INDEX) {
+ rc = mgs_set_next_index(obd, mti);
+ if (rc) {
+ CERROR("Can't get index (%d)\n", rc);
+ GOTO(out, rc);
}
}
- /* add a new open llog to mgs_open_llogs */
- OBD_ALLOC(mollog, sizeof(*mollog));
- if (!mollog) {
- CERROR("No memory for mollog.\n");
- return -ENOMEM;
+ /* create the log for the new target
+ and update the client/mdt logs */
+ rc = mgs_write_log_target(obd, mti);
+ if (rc) {
+ CERROR("Failed to write %s log (%d)\n",
+ mti->mti_svname, rc);
+ GOTO(out, rc);
}
- mollog->mol_id = id;
- mollog->mol_dentry = dentry;
- mollog->mol_update = 0;
-
- spin_lock(&mgs->mgs_llogs_lock);
- list_add(&mollog->mol_list, &mgs->mgs_open_llogs);
- spin_unlock(&mgs->mgs_llogs_lock);
- return 0;
+out:
+ lustre_pack_reply(req, 1, &rep_size, NULL);
+ /* send back the whole mti in the reply */
+ rep_mti = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*rep_mti));
+ memcpy(rep_mti, mti, sizeof(*rep_mti));
+ rep_mti->mti_rc = rc;
+ RETURN(rc);
}
int mgs_handle(struct ptlrpc_request *req)
{
- int fail = OBD_FAIL_MGS_ALL_REPLY_NET;
+ int fail = OBD_FAIL_MGMT_ALL_REPLY_NET;
int rc = 0;
- struct mgs_obd *mgs = NULL; /* quell gcc overwarning */
- struct obd_device *obd = NULL;
ENTRY;
+
+ CERROR("MGS handle\n");
- OBD_FAIL_RETURN(OBD_FAIL_MGS_ALL_REQUEST_NET | OBD_FAIL_ONCE, 0);
+ OBD_FAIL_RETURN(OBD_FAIL_MGMT_ALL_REQUEST_NET | OBD_FAIL_ONCE, 0);
LASSERT(current->journal_info == NULL);
- /* XXX identical to MDS */
- if (req->rq_reqmsg->opc != MGS_CONNECT) {
- struct mgs_export_data *med;
- int abort_recovery;
-
+ if (req->rq_reqmsg->opc != MGMT_CONNECT) {
if (req->rq_export == NULL) {
CERROR("lustre_mgs: operation %d on unconnected MGS\n",
req->rq_reqmsg->opc);
req->rq_status = -ENOTCONN;
GOTO(out, rc = -ENOTCONN);
}
-
- med = &req->rq_export->exp_mgs_data;
- obd = req->rq_export->exp_obd;
- mgs = &obd->u.mgs;
-
- /* sanity check: if the xid matches, the request must
- * be marked as a resent or replayed */
- if (req->rq_xid == med->med_mcd->mcd_last_xid)
- LASSERTF(lustre_msg_get_flags(req->rq_reqmsg) &
- (MSG_RESENT | MSG_REPLAY),
- "rq_xid "LPU64" matches last_xid, "
- "expected RESENT flag\n",
- req->rq_xid);
- /* else: note the opposite is not always true; a
- * RESENT req after a failover will usually not match
- * the last_xid, since it was likely never
- * committed. A REPLAYed request will almost never
- * match the last xid, however it could for a
- * committed, but still retained, open. */
-
- /* Check for aborted recovery. */
- spin_lock_bh(&obd->obd_processing_task_lock);
- abort_recovery = obd->obd_abort_recovery;
- spin_unlock_bh(&obd->obd_processing_task_lock);
- if (abort_recovery) {
- target_abort_recovery(obd);
- }
}
switch (req->rq_reqmsg->opc) {
- case MGS_CONNECT:
+ case MGMT_CONNECT:
DEBUG_REQ(D_INODE, req, "connect");
- OBD_FAIL_RETURN(OBD_FAIL_MGS_CONNECT_NET, 0);
+ OBD_FAIL_RETURN(OBD_FAIL_MGMT_CONNECT_NET, 0);
rc = target_handle_connect(req, mgs_handle);
- if (!rc) {
- /* Now that we have an export, set mgs. */
- obd = req->rq_export->exp_obd;
- mgs = mgs_req2mgs(req);
- }
break;
-
- case MGS_DISCONNECT:
+ case MGMT_DISCONNECT:
DEBUG_REQ(D_INODE, req, "disconnect");
- OBD_FAIL_RETURN(OBD_FAIL_MGS_DISCONNECT_NET, 0);
+ OBD_FAIL_RETURN(OBD_FAIL_MGMT_DISCONNECT_NET, 0);
rc = target_handle_disconnect(req);
req->rq_status = rc; /* superfluous? */
break;
+ case MGMT_TARGET_ADD:
+ CDEBUG(D_INODE, "target add\n");
+ rc = mgs_handle_target_add(req);
+ break;
+ case MGMT_TARGET_DEL:
+ CDEBUG(D_INODE, "target del\n");
+ //rc = mgs_handle_target_del(req);
+ break;
+
+ case LDLM_ENQUEUE:
+ DEBUG_REQ(D_INODE, req, "enqueue");
+ OBD_FAIL_RETURN(OBD_FAIL_LDLM_ENQUEUE, 0);
+ rc = ldlm_handle_enqueue(req, ldlm_server_completion_ast,
+ ldlm_server_blocking_ast, NULL);
+ fail = OBD_FAIL_LDLM_REPLY;
+ break;
+ case LDLM_BL_CALLBACK:
+ case LDLM_CP_CALLBACK:
+ DEBUG_REQ(D_INODE, req, "callback");
+ CERROR("callbacks should not happen on MDS\n");
+ LBUG();
+ OBD_FAIL_RETURN(OBD_FAIL_LDLM_BL_CALLBACK, 0);
+ break;
+
case OBD_PING:
DEBUG_REQ(D_INODE, req, "ping");
rc = target_handle_ping(req);
LASSERT(current->journal_info == NULL);
- /* If we're DISCONNECTing, the mgs_export_data is already freed */
- if (!rc && req->rq_reqmsg->opc != MGS_DISCONNECT) {
- struct mgs_export_data *med = &req->rq_export->exp_mgs_data;
- req->rq_repmsg->last_xid =
- le64_to_cpu(med->med_mcd->mcd_last_xid);
-
- target_committed_to_req(req);
- }
-
- EXIT;
out:
-
- if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_LAST_REPLAY) {
- if (obd && obd->obd_recovering) {
- DEBUG_REQ(D_HA, req, "LAST_REPLAY, queuing reply");
- return target_queue_final_reply(req, rc);
- }
- /* Lost a race with recovery; let the error path DTRT. */
- rc = req->rq_status = -ENOTCONN;
- }
-
target_send_reply(req, rc, fail);
- return 0;
+ RETURN(0);
}
static int mgt_setup(struct obd_device *obd, obd_count len, void *buf)
int rc = 0;
ENTRY;
- lprocfs_init_vars(mgt, &lvars);
- lprocfs_obd_setup(obd, lvars.obd_vars);
+ lprocfs_init_vars(mgt, &lvars);
+ lprocfs_obd_setup(obd, lvars.obd_vars);
mgs->mgs_service =
ptlrpc_init_svc(MGS_NBUFS, MGS_BUFSIZE, MGS_MAXREQSIZE,
- MGS_REQUEST_PORTAL, MGC_REPLY_PORTAL,
- MGS_SERVICE_WATCHDOG_TIMEOUT,
- mgs_handle, "mgs", obd->obd_proc_entry, NULL);
+ MGS_MAXREPSIZE, MGS_REQUEST_PORTAL,
+ MGC_REPLY_PORTAL, MGS_SERVICE_WATCHDOG_TIMEOUT,
+ mgs_handle, "mgs", obd->obd_proc_entry, NULL,
+ MGT_NUM_THREADS);
if (!mgs->mgs_service) {
CERROR("failed to start service\n");
GOTO(err_lprocfs, rc = -ENOMEM);
}
- rc = ptlrpc_start_n_threads(obd, mgs->mgs_service, MGT_NUM_THREADS,
- "ll_mgt");
+ rc = ptlrpc_start_threads(obd, mgs->mgs_service, "ll_mgt");
if (rc)
GOTO(err_thread, rc);
return rc;
}
+
static int mgt_cleanup(struct obd_device *obd)
{
struct mgs_obd *mgs = &obd->u.mgs;
}
struct lvfs_callback_ops mgs_lvfs_ops = {
- l_fid2dentry: mgs_lvfs_fid2dentry,
- l_open_llog: mgs_lvfs_open_llog,
+ // l_fid2dentry: mgs_lvfs_fid2dentry,
+ // l_open_llog: mgs_lvfs_open_llog,
};
/* use obd ops to offer management infrastructure */
static struct obd_ops mgs_obd_ops = {
.o_owner = THIS_MODULE,
.o_connect = mgs_connect,
- .o_init_export = mgs_init_export,
.o_disconnect = mgs_disconnect,
.o_setup = mgs_setup,
.o_precleanup = mgs_precleanup,