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 set_osc_active(struct obd_import *imp, int active)
74 struct obd_device *notify_obd = imp->imp_obd->u.cli.cl_containing_lov;
76 if (notify_obd == NULL)
79 /* How gross is _this_? */
80 if (!list_empty(¬ify_obd->obd_exports)) {
82 struct lustre_handle fakeconn;
83 struct obd_ioctl_data ioc_data;
84 struct obd_export *exp =
85 list_entry(notify_obd->obd_exports.next,
86 struct obd_export, exp_obd_chain);
88 fakeconn.addr = (__u64)(unsigned long)exp;
89 fakeconn.cookie = exp->exp_cookie;
90 ioc_data.ioc_inlbuf1 = imp->imp_obd->obd_uuid;
91 ioc_data.ioc_offset = active;
92 rc = obd_iocontrol(IOC_LOV_SET_OSC_ACTIVE, &fakeconn,
93 sizeof ioc_data, &ioc_data, NULL);
95 CERROR("disabling %s on LOV %p/%s: %d\n",
96 imp->imp_obd->obd_uuid, notify_obd,
97 notify_obd->obd_uuid, rc);
99 CDEBUG(D_HA, "No exports for obd %p/%s, can't notify about "
100 "%p\n", notify_obd, notify_obd->obd_uuid,
101 imp->imp_obd->obd_uuid);
105 static void prepare_osc(struct obd_import *imp)
107 struct ldlm_namespace *ns = imp->imp_obd->obd_namespace;
109 CDEBUG(D_HA, "invalidating all locks for OST imp %p (to %s):\n",
110 imp, imp->imp_connection->c_remote_uuid);
111 ldlm_namespace_dump(ns);
112 ldlm_namespace_cleanup(ns, 1 /* no network ops */);
114 abort_inflight_for_import(imp);
116 set_osc_active(imp, 0 /* inactive */);
119 static void prepare_mdc(struct obd_import *imp)
121 struct ldlm_namespace *ns = imp->imp_obd->obd_namespace;
122 ldlm_cli_cancel_unused(ns, NULL, LDLM_FL_LOCAL_ONLY);
125 static int ll_prepare_recovery(struct ptlrpc_connection *conn)
127 struct list_head *tmp;
129 list_for_each(tmp, &conn->c_imports) {
130 struct obd_import *imp = list_entry(tmp, struct obd_import,
133 if (imp->imp_obd->obd_type->typ_ops->o_brw)
139 return ptlrpc_run_recovery_upcall(conn);
142 static void reconnect_osc(struct obd_import *imp)
144 int rc = ptlrpc_reconnect_import(imp, OST_CONNECT);
146 set_osc_active(imp, 1 /* active */);
148 CDEBUG(D_HA, "reconnection failed, not reactivating OSC %s\n",
149 imp->imp_obd->obd_uuid);
152 static int reconnect_mdc(struct obd_import *imp)
154 return ptlrpc_reconnect_import(imp, MDS_CONNECT);
157 static int ll_reconnect(struct ptlrpc_connection *conn)
159 struct list_head *tmp;
164 /* XXX c_lock semantics! */
165 conn->c_level = LUSTRE_CONN_CON;
167 /* XXX this code MUST be shared with class_obd_connect! */
168 list_for_each(tmp, &conn->c_imports) {
169 struct obd_import *imp = list_entry(tmp, struct obd_import,
171 if (imp->imp_obd->obd_type->typ_ops->o_brw) {
172 /* XXX what to do if we fail? */
175 int rc = reconnect_mdc(imp);
179 /* make sure we don't try to replay for dead imps?
181 * else imp->imp_connection = NULL;
190 conn->c_level = LUSTRE_CONN_FULL;
194 conn->c_level = LUSTRE_CONN_RECOVD;
195 /* this will replay, up the c_level, recovd_conn_fixed and continue
196 * reqs. also, makes a mean cup of coffee.
198 RETURN(ptlrpc_replay(conn));
201 int ll_recover(struct recovd_data *rd, int phase)
203 struct ptlrpc_connection *conn = class_rd2conn(rd);
209 case PTLRPC_RECOVD_PHASE_PREPARE:
210 RETURN(ll_prepare_recovery(conn));
211 case PTLRPC_RECOVD_PHASE_RECOVER:
212 RETURN(ll_reconnect(conn));
213 case PTLRPC_RECOVD_PHASE_FAILURE:
214 RETURN(ll_retry_recovery(conn));