1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Lustre Lite recovery infrastructure.
6 * Copyright (C) 2002 Cluster File Systems Inc.
9 #define DEBUG_SUBSYSTEM S_LLITE
11 #include <linux/lustre_lite.h>
12 #include <linux/lustre_ha.h>
13 #include <linux/lustre_dlm.h>
14 #include <linux/lustre_idl.h>
15 #include <linux/obd_lov.h> /* for IOC_LOV_SET_OSC_ACTIVE */
17 static int ll_retry_recovery(struct ptlrpc_connection *conn)
23 /* XXX looks a lot like super.c:invalidate_request_list, don't it? */
24 static void abort_inflight_for_import(struct obd_import *imp)
26 struct list_head *tmp, *n;
28 /* Make sure that no new requests get processed for this import.
29 * ptlrpc_queue_wait must (and does) hold c_lock while testing this
30 * flags and then putting requests on sending_head or delayed_head.
32 spin_lock(&imp->imp_connection->c_lock);
33 imp->imp_flags |= IMP_INVALID;
34 spin_unlock(&imp->imp_connection->c_lock);
36 list_for_each_safe(tmp, n, &imp->imp_connection->c_sending_head) {
37 struct ptlrpc_request *req =
38 list_entry(tmp, struct ptlrpc_request, rq_list);
40 if (req->rq_import != imp)
43 if (req->rq_flags & PTL_RPC_FL_REPLIED) {
44 /* no need to replay, just discard */
45 CERROR("uncommitted req xid "LPD64" op %d to OST %s\n",
46 (unsigned long long)req->rq_xid,
48 imp->imp_obd->u.cli.cl_target_uuid);
49 ptlrpc_req_finished(req);
51 CERROR("inflight req xid "LPD64" op %d to OST %s\n",
52 (unsigned long long)req->rq_xid,
54 imp->imp_obd->u.cli.cl_target_uuid);
56 req->rq_flags |= PTL_RPC_FL_ERR;
57 wake_up(&req->rq_wait_for_rep);
61 list_for_each_safe(tmp, n, &imp->imp_connection->c_delayed_head) {
62 struct ptlrpc_request *req =
63 list_entry(tmp, struct ptlrpc_request, rq_list);
64 CERROR("aborting waiting req xid "LPD64" op %d to OST %s\n",
65 (unsigned long long)req->rq_xid, req->rq_reqmsg->opc,
66 imp->imp_obd->u.cli.cl_target_uuid);
67 req->rq_flags |= PTL_RPC_FL_ERR;
68 wake_up(&req->rq_wait_for_rep);
72 static void prepare_ost(struct obd_import *imp)
75 struct ldlm_namespace *ns = imp->imp_obd->obd_namespace;
76 struct obd_device *notify_obd = imp->imp_obd->u.cli.cl_containing_lov;
78 CDEBUG(D_HA, "invalidating all locks for OST imp %p (to %s):\n",
79 imp, imp->imp_connection->c_remote_uuid);
80 ldlm_namespace_dump(ns);
81 ldlm_namespace_cleanup(ns, 1 /* no network ops */);
83 abort_inflight_for_import(imp);
85 /* How gross is _this_? */
86 if (!list_empty(¬ify_obd->obd_exports)) {
87 struct lustre_handle fakeconn;
88 struct obd_ioctl_data ioc_data;
89 struct obd_export *exp =
90 list_entry(¬ify_obd->obd_exports.next,
91 struct obd_export, exp_obd_chain);
92 fakeconn.addr = (__u64)(unsigned long)exp;
93 fakeconn.cookie = exp->exp_cookie;
94 ioc_data.ioc_inlbuf1 = imp->imp_obd->obd_uuid;
95 ioc_data.ioc_offset = 0; /* inactive */
96 rc = obd_iocontrol(IOC_LOV_SET_OSC_ACTIVE, &fakeconn,
97 sizeof ioc_data, &ioc_data, NULL);
99 CERROR("disabling %s on LOV %p/%s: %d\n",
100 imp->imp_obd->obd_uuid, notify_obd,
101 notify_obd->obd_uuid, rc);
103 CDEBUG(D_HA, "No exports for obd %p/%s, can't notify about %p\n",
104 notify_obd, notify_obd->obd_uuid, imp->imp_obd->obd_uuid);
108 static int ll_prepare_recovery(struct ptlrpc_connection *conn)
110 struct list_head *tmp;
112 list_for_each(tmp, &conn->c_imports) {
113 struct obd_import *imp = list_entry(tmp, struct obd_import,
116 if (imp->imp_obd->obd_type->typ_ops->o_brw)
120 return ptlrpc_run_recovery_upcall(conn);
123 static void reconnect_ost(struct obd_import *imp)
125 (void)ptlrpc_reconnect_import(imp, OST_CONNECT);
128 static int ll_reconnect(struct ptlrpc_connection *conn)
130 struct list_head *tmp;
135 /* XXX c_lock semantics! */
136 conn->c_level = LUSTRE_CONN_CON;
138 /* XXX this code MUST be shared with class_obd_connect! */
139 list_for_each(tmp, &conn->c_imports) {
140 struct obd_import *imp = list_entry(tmp, struct obd_import,
142 if (imp->imp_obd->obd_type->typ_ops->o_brw) {
143 /* XXX what to do if we fail? */
146 int rc = ptlrpc_reconnect_import(imp, MDS_CONNECT);
149 /* XXX obd_cancel_unused */
151 /* make sure we don't try to replay for dead imps?
153 * else imp->imp_connection = NULL;
162 conn->c_level = LUSTRE_CONN_FULL;
166 conn->c_level = LUSTRE_CONN_RECOVD;
167 /* this will replay, up the c_level, recovd_conn_fixed and continue reqs.
168 * also, makes a mean cup of coffee.
170 RETURN(ptlrpc_replay(conn));
173 int ll_recover(struct recovd_data *rd, int phase)
175 struct ptlrpc_connection *conn = class_rd2conn(rd);
181 case PTLRPC_RECOVD_PHASE_PREPARE:
182 RETURN(ll_prepare_recovery(conn));
183 case PTLRPC_RECOVD_PHASE_RECOVER:
184 RETURN(ll_reconnect(conn));
185 case PTLRPC_RECOVD_PHASE_FAILURE:
186 RETURN(ll_retry_recovery(conn));