Whamcloud - gitweb
Lproc-snmp code drop
[fs/lustre-release.git] / lustre / llite / recover.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Lustre Lite recovery infrastructure.
5  *
6  * Copyright (C) 2002 Cluster File Systems Inc.
7  */
8
9 #define DEBUG_SUBSYSTEM S_LLITE
10
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 */
16
17 static int ll_retry_recovery(struct ptlrpc_connection *conn)
18 {
19         ENTRY;
20         RETURN(0);
21 }
22
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)
25 {
26         struct list_head *tmp, *n;
27
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.
31          */
32         spin_lock(&imp->imp_connection->c_lock);
33         imp->imp_flags |= IMP_INVALID;
34         spin_unlock(&imp->imp_connection->c_lock);
35
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);
39
40                 if (req->rq_import != imp)
41                         continue;
42
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,
47                                req->rq_reqmsg->opc,
48                                imp->imp_obd->u.cli.cl_target_uuid);
49                         ptlrpc_req_finished(req);
50                 } else {
51                         CERROR("inflight req xid "LPD64" op %d to OST %s\n",
52                                (unsigned long long)req->rq_xid,
53                                req->rq_reqmsg->opc,
54                                imp->imp_obd->u.cli.cl_target_uuid);
55
56                         req->rq_flags |= PTL_RPC_FL_ERR;
57                         wake_up(&req->rq_wait_for_rep);
58                 }
59         }
60
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);
69         }
70 }
71
72 static void set_osc_active(struct obd_import *imp, int active)
73 {
74         struct obd_device *notify_obd = imp->imp_obd->u.cli.cl_containing_lov;
75
76         if (notify_obd == NULL)
77                 return;
78
79         /* How gross is _this_? */
80         if (!list_empty(&notify_obd->obd_exports)) {
81                 int rc;
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);
87
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);
94                 if (rc)
95                         CERROR("disabling %s on LOV %p/%s: %d\n",
96                                imp->imp_obd->obd_uuid, notify_obd,
97                                notify_obd->obd_uuid, rc);
98         } else {
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);
102         }
103 }
104
105 static void prepare_osc(struct obd_import *imp)
106 {
107         struct ldlm_namespace *ns = imp->imp_obd->obd_namespace;
108
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 */);
113
114         abort_inflight_for_import(imp);
115
116         set_osc_active(imp, 0 /* inactive */);
117 }
118
119 static void prepare_mdc(struct obd_import *imp)
120 {
121         struct ldlm_namespace *ns = imp->imp_obd->obd_namespace;
122         ldlm_cli_cancel_unused(ns, NULL, LDLM_FL_LOCAL_ONLY);
123 }
124
125 static int ll_prepare_recovery(struct ptlrpc_connection *conn)
126 {
127         struct list_head *tmp;
128
129         list_for_each(tmp, &conn->c_imports) {
130                 struct obd_import *imp = list_entry(tmp, struct obd_import,
131                                                     imp_chain);
132
133                 if (imp->imp_obd->obd_type->typ_ops->o_brw)
134                         prepare_osc(imp);
135                 else
136                         prepare_mdc(imp);
137         }
138
139         return ptlrpc_run_recovery_upcall(conn);
140 }
141
142 static void reconnect_osc(struct obd_import *imp)
143 {
144         int rc = ptlrpc_reconnect_import(imp, OST_CONNECT);
145         if (rc == 0)
146                 set_osc_active(imp, 1 /* active */);
147         else
148                 CDEBUG(D_HA, "reconnection failed, not reactivating OSC %s\n",
149                        imp->imp_obd->obd_uuid);
150 }
151
152 static int reconnect_mdc(struct obd_import *imp)
153 {
154         return ptlrpc_reconnect_import(imp, MDS_CONNECT);
155 }
156
157 static int ll_reconnect(struct ptlrpc_connection *conn)
158 {
159         struct list_head *tmp;
160         int need_replay = 0;
161
162         ENTRY;
163
164         /* XXX c_lock semantics! */
165         conn->c_level = LUSTRE_CONN_CON;
166
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,
170                                                     imp_chain);
171                 if (imp->imp_obd->obd_type->typ_ops->o_brw) {
172                         /* XXX what to do if we fail? */
173                         reconnect_osc(imp);
174                 } else {
175                         int rc = reconnect_mdc(imp);
176                         if (!rc) {
177                                 need_replay = 1;
178                         }
179                         /* make sure we don't try to replay for dead imps?
180                          *
181                          * else imp->imp_connection = NULL;
182                          *
183                          */
184
185                 }
186         }
187
188         if (!need_replay) {
189                 /* all done! */
190                 conn->c_level = LUSTRE_CONN_FULL;
191                 RETURN(0);
192         }
193
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.
197          */
198         RETURN(ptlrpc_replay(conn));
199 }
200
201 int ll_recover(struct recovd_data *rd, int phase)
202 {
203         struct ptlrpc_connection *conn = class_rd2conn(rd);
204
205         LASSERT(conn);
206         ENTRY;
207
208         switch (phase) {
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));
215         }
216
217         LBUG();
218         RETURN(-ENOSYS);
219 }