1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#define DEBUG_SUBSYSTEM S_RPC
38#include <linux/libcfs/libcfs.h>
39
40#include <obd_support.h>
41#include <lustre_ha.h>
42#include <lustre_net.h>
43#include <lustre_import.h>
44#include <lustre_export.h>
45#include <obd.h>
46#include <obd_class.h>
47#include <linux/list.h>
48
49#include "ptlrpc_internal.h"
50
51
52
53
54
55void ptlrpc_initiate_recovery(struct obd_import *imp)
56{
57 CDEBUG(D_HA, "%s: starting recovery\n", obd2cli_tgt(imp->imp_obd));
58 ptlrpc_connect_import(imp);
59}
60
61
62
63
64
65int ptlrpc_replay_next(struct obd_import *imp, int *inflight)
66{
67 int rc = 0;
68 struct list_head *tmp, *pos;
69 struct ptlrpc_request *req = NULL;
70 __u64 last_transno;
71
72 *inflight = 0;
73
74
75
76
77 spin_lock(&imp->imp_lock);
78 imp->imp_last_transno_checked = 0;
79 ptlrpc_free_committed(imp);
80 last_transno = imp->imp_last_replay_transno;
81
82 CDEBUG(D_HA, "import %p from %s committed %llu last %llu\n",
83 imp, obd2cli_tgt(imp->imp_obd),
84 imp->imp_peer_committed_transno, last_transno);
85
86
87 if (!list_empty(&imp->imp_committed_list)) {
88 tmp = imp->imp_committed_list.prev;
89 req = list_entry(tmp, struct ptlrpc_request, rq_replay_list);
90
91
92 if (req->rq_transno > last_transno) {
93 if (!imp->imp_resend_replay ||
94 imp->imp_replay_cursor == &imp->imp_committed_list)
95 imp->imp_replay_cursor = imp->imp_replay_cursor->next;
96
97 while (imp->imp_replay_cursor !=
98 &imp->imp_committed_list) {
99 req = list_entry(imp->imp_replay_cursor,
100 struct ptlrpc_request,
101 rq_replay_list);
102 if (req->rq_transno > last_transno)
103 break;
104
105 req = NULL;
106 LASSERT(!list_empty(imp->imp_replay_cursor));
107 imp->imp_replay_cursor =
108 imp->imp_replay_cursor->next;
109 }
110 } else {
111
112 imp->imp_replay_cursor = &imp->imp_committed_list;
113 req = NULL;
114 }
115 }
116
117
118
119
120 if (!req) {
121 list_for_each_safe(tmp, pos, &imp->imp_replay_list) {
122 req = list_entry(tmp, struct ptlrpc_request,
123 rq_replay_list);
124
125 if (req->rq_transno > last_transno)
126 break;
127 req = NULL;
128 }
129 }
130
131
132
133
134
135
136 if (req && imp->imp_resend_replay)
137 lustre_msg_add_flags(req->rq_reqmsg, MSG_RESENT);
138
139
140
141
142 if (req && imp->imp_resend_replay &&
143 list_empty(&req->rq_unreplied_list)) {
144 ptlrpc_add_unreplied(req);
145 imp->imp_known_replied_xid = ptlrpc_known_replied_xid(imp);
146 }
147
148 imp->imp_resend_replay = 0;
149 spin_unlock(&imp->imp_lock);
150
151 if (req) {
152
153
154
155 LASSERT(!list_empty(&req->rq_unreplied_list));
156
157 rc = ptlrpc_replay_req(req);
158 if (rc) {
159 CERROR("recovery replay error %d for req %llu\n",
160 rc, req->rq_xid);
161 return rc;
162 }
163 *inflight = 1;
164 }
165 return rc;
166}
167
168
169
170
171
172int ptlrpc_resend(struct obd_import *imp)
173{
174 struct ptlrpc_request *req, *next;
175
176
177
178
179
180
181
182 spin_lock(&imp->imp_lock);
183 if (imp->imp_state != LUSTRE_IMP_RECOVER) {
184 spin_unlock(&imp->imp_lock);
185 return -1;
186 }
187
188 list_for_each_entry_safe(req, next, &imp->imp_sending_list, rq_list) {
189 LASSERTF((long)req > PAGE_SIZE && req != LP_POISON,
190 "req %p bad\n", req);
191 LASSERTF(req->rq_type != LI_POISON, "req %p freed\n", req);
192
193
194
195
196
197 if (!ptlrpc_no_resend(req) &&
198 (req->rq_timedout || !req->rq_allow_replay))
199 ptlrpc_resend_req(req);
200 }
201 spin_unlock(&imp->imp_lock);
202
203 OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_ENQUEUE_OLD_EXPORT, 2);
204 return 0;
205}
206
207
208
209
210
211void ptlrpc_wake_delayed(struct obd_import *imp)
212{
213 struct list_head *tmp, *pos;
214 struct ptlrpc_request *req;
215
216 spin_lock(&imp->imp_lock);
217 list_for_each_safe(tmp, pos, &imp->imp_delayed_list) {
218 req = list_entry(tmp, struct ptlrpc_request, rq_list);
219
220 DEBUG_REQ(D_HA, req, "waking (set %p):", req->rq_set);
221 ptlrpc_client_wake_req(req);
222 }
223 spin_unlock(&imp->imp_lock);
224}
225
226void ptlrpc_request_handle_notconn(struct ptlrpc_request *failed_req)
227{
228 struct obd_import *imp = failed_req->rq_import;
229
230 CDEBUG(D_HA, "import %s of %s@%s abruptly disconnected: reconnecting\n",
231 imp->imp_obd->obd_name, obd2cli_tgt(imp->imp_obd),
232 imp->imp_connection->c_remote_uuid.uuid);
233
234 if (ptlrpc_set_import_discon(imp,
235 lustre_msg_get_conn_cnt(failed_req->rq_reqmsg))) {
236 if (!imp->imp_replayable) {
237 CDEBUG(D_HA, "import %s@%s for %s not replayable, auto-deactivating\n",
238 obd2cli_tgt(imp->imp_obd),
239 imp->imp_connection->c_remote_uuid.uuid,
240 imp->imp_obd->obd_name);
241 ptlrpc_deactivate_import(imp);
242 }
243
244 if (imp->imp_deactive == 0)
245 ptlrpc_connect_import(imp);
246 }
247
248
249
250
251 spin_lock(&failed_req->rq_lock);
252 if (!failed_req->rq_no_resend)
253 failed_req->rq_resend = 1;
254 spin_unlock(&failed_req->rq_lock);
255}
256
257
258
259
260
261
262
263
264int ptlrpc_set_import_active(struct obd_import *imp, int active)
265{
266 struct obd_device *obd = imp->imp_obd;
267 int rc = 0;
268
269 LASSERT(obd);
270
271
272
273
274 if (!active) {
275 LCONSOLE_WARN("setting import %s INACTIVE by administrator request\n",
276 obd2cli_tgt(imp->imp_obd));
277
278
279
280
281 spin_lock(&imp->imp_lock);
282 imp->imp_deactive = 1;
283 spin_unlock(&imp->imp_lock);
284
285 obd_import_event(imp->imp_obd, imp, IMP_EVENT_DEACTIVATE);
286
287 ptlrpc_invalidate_import(imp);
288 }
289
290
291 if (active) {
292 CDEBUG(D_HA, "setting import %s VALID\n",
293 obd2cli_tgt(imp->imp_obd));
294
295 spin_lock(&imp->imp_lock);
296 imp->imp_deactive = 0;
297 spin_unlock(&imp->imp_lock);
298 obd_import_event(imp->imp_obd, imp, IMP_EVENT_ACTIVATE);
299
300 rc = ptlrpc_recover_import(imp, NULL, 0);
301 }
302
303 return rc;
304}
305EXPORT_SYMBOL(ptlrpc_set_import_active);
306
307
308int ptlrpc_recover_import(struct obd_import *imp, char *new_uuid, int async)
309{
310 int rc = 0;
311
312 spin_lock(&imp->imp_lock);
313 if (imp->imp_state == LUSTRE_IMP_NEW || imp->imp_deactive ||
314 atomic_read(&imp->imp_inval_count))
315 rc = -EINVAL;
316 spin_unlock(&imp->imp_lock);
317 if (rc)
318 goto out;
319
320
321 ptlrpc_set_import_discon(imp, 0);
322
323 if (new_uuid) {
324 struct obd_uuid uuid;
325
326
327 obd_str2uuid(&uuid, new_uuid);
328 rc = import_set_conn_priority(imp, &uuid);
329 if (rc)
330 goto out;
331 }
332
333
334 spin_lock(&imp->imp_lock);
335 if (imp->imp_state != LUSTRE_IMP_DISCON) {
336 imp->imp_force_verify = 1;
337 rc = -EALREADY;
338 }
339 spin_unlock(&imp->imp_lock);
340 if (rc)
341 goto out;
342
343 rc = ptlrpc_connect_import(imp);
344 if (rc)
345 goto out;
346
347 if (!async) {
348 struct l_wait_info lwi;
349 int secs = cfs_time_seconds(obd_timeout);
350
351 CDEBUG(D_HA, "%s: recovery started, waiting %u seconds\n",
352 obd2cli_tgt(imp->imp_obd), secs);
353
354 lwi = LWI_TIMEOUT(secs, NULL, NULL);
355 rc = l_wait_event(imp->imp_recovery_waitq,
356 !ptlrpc_import_in_recovery(imp), &lwi);
357 CDEBUG(D_HA, "%s: recovery finished\n",
358 obd2cli_tgt(imp->imp_obd));
359 }
360
361out:
362 return rc;
363}
364EXPORT_SYMBOL(ptlrpc_recover_import);
365
366int ptlrpc_import_in_recovery(struct obd_import *imp)
367{
368 int in_recovery = 1;
369
370 spin_lock(&imp->imp_lock);
371 if (imp->imp_state == LUSTRE_IMP_FULL ||
372 imp->imp_state == LUSTRE_IMP_CLOSED ||
373 imp->imp_state == LUSTRE_IMP_DISCON ||
374 imp->imp_obd->obd_no_recov)
375 in_recovery = 0;
376 spin_unlock(&imp->imp_lock);
377
378 return in_recovery;
379}
380