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