Whamcloud - gitweb
land 1.0.1 fixes on main development branch (head)
[fs/lustre-release.git] / lustre / ptlrpc / recover.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Portal-RPC reconnection and replay operations, for use in recovery.
5  *
6  *  Copyright (c) 2002, 2003 Cluster File Systems, Inc.
7  *   Author: Mike Shaver <shaver@clusterfs.com>
8  *
9  *   This file is part of Lustre, http://www.lustre.org.
10  *
11  *   Lustre is free software; you can redistribute it and/or
12  *   modify it under the terms of version 2 of the GNU General Public
13  *   License as published by the Free Software Foundation.
14  *
15  *   Lustre is distributed in the hope that it will be useful,
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *   GNU General Public License for more details.
19  *
20  *   You should have received a copy of the GNU General Public License
21  *   along with Lustre; if not, write to the Free Software
22  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 #define DEBUG_SUBSYSTEM S_RPC
26 #ifdef __KERNEL__
27 # include <linux/config.h>
28 # include <linux/module.h>
29 # include <linux/kmod.h>
30 #else
31 # include <liblustre.h>
32 #endif
33
34 #include <linux/obd_support.h>
35 #include <linux/lustre_ha.h>
36 #include <linux/lustre_net.h>
37 #include <linux/lustre_import.h>
38 #include <linux/lustre_export.h>
39 #include <linux/obd.h>
40 #include <linux/obd_ost.h>
41 #include <linux/obd_class.h>
42 #include <linux/obd_lov.h> /* for IOC_LOV_SET_OSC_ACTIVE */
43
44 #include "ptlrpc_internal.h"
45
46 static int ptlrpc_recover_import_no_retry(struct obd_import *, char *);
47
48 void ptlrpc_run_recovery_over_upcall(struct obd_device *obd)
49 {
50         char *argv[4];
51         char *envp[3];
52         int rc;
53
54         ENTRY;
55         argv[0] = obd_lustre_upcall;
56         argv[1] = "RECOVERY_OVER";
57         argv[2] = obd->obd_uuid.uuid;
58         argv[3] = NULL;
59
60         envp[0] = "HOME=/";
61         envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
62         envp[2] = NULL;
63
64         rc = USERMODEHELPER(argv[0], argv, envp);
65         if (rc < 0) {
66                 CERROR("Error invoking recovery upcall %s %s %s: %d; check "
67                        "/proc/sys/lustre/upcall\n",
68                        argv[0], argv[1], argv[2], rc);
69
70         } else {
71                 CERROR("Invoked upcall %s %s %s",
72                        argv[0], argv[1], argv[2]);
73         }
74 }
75
76 void ptlrpc_run_failed_import_upcall(struct obd_import* imp)
77 {
78 #ifdef __KERNEL__
79         char *argv[7];
80         char *envp[3];
81         int rc;
82
83         ENTRY;
84         argv[0] = obd_lustre_upcall;
85         argv[1] = "FAILED_IMPORT";
86         argv[2] = imp->imp_target_uuid.uuid;
87         argv[3] = imp->imp_obd->obd_name;
88         argv[4] = imp->imp_connection->c_remote_uuid.uuid;
89         argv[5] = imp->imp_obd->obd_uuid.uuid;
90         argv[6] = NULL;
91
92         envp[0] = "HOME=/";
93         envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
94         envp[2] = NULL;
95
96         rc = USERMODEHELPER(argv[0], argv, envp);
97         if (rc < 0) {
98                 CERROR("Error invoking recovery upcall %s %s %s %s %s: %d; "
99                        "check /proc/sys/lustre/lustre_upcall\n",
100                        argv[0], argv[1], argv[2], argv[3], argv[4],rc);
101
102         } else {
103                 CERROR("Invoked upcall %s %s %s %s %s\n",
104                        argv[0], argv[1], argv[2], argv[3], argv[4]);
105         }
106 #else
107         ptlrpc_recover_import(imp, NULL);
108 #endif
109 }
110
111 int ptlrpc_replay(struct obd_import *imp)
112 {
113         int rc = 0;
114         struct list_head *tmp, *pos;
115         struct ptlrpc_request *req;
116         unsigned long flags;
117         ENTRY;
118
119         /* It might have committed some after we last spoke, so make sure we
120          * get rid of them now.
121          */
122         spin_lock_irqsave(&imp->imp_lock, flags);
123         ptlrpc_free_committed(imp);
124         spin_unlock_irqrestore(&imp->imp_lock, flags);
125
126         CDEBUG(D_HA, "import %p from %s has committed "LPD64"\n",
127                imp, imp->imp_target_uuid.uuid, imp->imp_peer_committed_transno);
128
129         list_for_each(tmp, &imp->imp_replay_list) {
130                 req = list_entry(tmp, struct ptlrpc_request, rq_list);
131                 DEBUG_REQ(D_HA, req, "RETAINED: ");
132         }
133
134         /* Do I need to hold a lock across this iteration?  We shouldn't be
135          * racing with any additions to the list, because we're in recovery
136          * and are therefore not processing additional requests to add.  Calls
137          * to ptlrpc_free_committed might commit requests, but nothing "newer"
138          * than the one we're replaying (it can't be committed until it's
139          * replayed, and we're doing that here).  l_f_e_safe protects against
140          * problems with the current request being committed, in the unlikely
141          * event of that race.  So, in conclusion, I think that it's safe to
142          * perform this list-walk without the imp_lock held.
143          *
144          * But, the {mdc,osc}_replay_open callbacks both iterate
145          * request lists, and have comments saying they assume the
146          * imp_lock is being held by ptlrpc_replay, but it's not. it's
147          * just a little race...
148          */
149         list_for_each_safe(tmp, pos, &imp->imp_replay_list) {
150                 req = list_entry(tmp, struct ptlrpc_request, rq_list);
151
152                 DEBUG_REQ(D_HA, req, "REPLAY:");
153
154                 rc = ptlrpc_replay_req(req);
155
156                 if (rc) {
157                         CERROR("recovery replay error %d for req "LPD64"\n",
158                                rc, req->rq_xid);
159                         RETURN(rc);
160                 }
161         }
162
163         RETURN(0);
164 }
165
166 int ptlrpc_resend(struct obd_import *imp)
167 {
168         struct list_head *tmp, *pos;
169         struct ptlrpc_request *req;
170         unsigned long flags;
171
172         ENTRY;
173
174         /* As long as we're in recovery, nothing should be added to the sending
175          * list, so we don't need to hold the lock during this iteration and
176          * resend process.
177          */
178         /* Well... what if lctl recover is called twice at the same time?
179          */
180         spin_lock_irqsave(&imp->imp_lock, flags);
181         LASSERT(imp->imp_state == LUSTRE_IMP_RECOVER);
182         spin_unlock_irqrestore(&imp->imp_lock, flags);
183
184         list_for_each_safe(tmp, pos, &imp->imp_sending_list) {
185                 req = list_entry(tmp, struct ptlrpc_request, rq_list);
186                 ptlrpc_resend_req(req);
187         }
188
189         RETURN(0);
190 }
191
192 void ptlrpc_wake_delayed(struct obd_import *imp)
193 {
194         unsigned long flags;
195         struct list_head *tmp, *pos;
196         struct ptlrpc_request *req;
197
198         spin_lock_irqsave(&imp->imp_lock, flags);
199         list_for_each_safe(tmp, pos, &imp->imp_delayed_list) {
200                 req = list_entry(tmp, struct ptlrpc_request, rq_list);
201
202                 ptlrpc_put_connection(req->rq_connection);
203                 req->rq_connection =
204                        ptlrpc_connection_addref(req->rq_import->imp_connection);
205
206                 if (req->rq_set) {
207                         DEBUG_REQ(D_HA, req, "waking (set %p):", req->rq_set);
208                         wake_up(&req->rq_set->set_waitq);
209                 } else {
210                         DEBUG_REQ(D_HA, req, "waking:");
211                         wake_up(&req->rq_reply_waitq);
212                 }
213         }
214         spin_unlock_irqrestore(&imp->imp_lock, flags);
215 }
216
217 inline void ptlrpc_invalidate_import_state(struct obd_import *imp)
218 {
219         struct obd_device *obd = imp->imp_obd;
220         struct ldlm_namespace *ns = obd->obd_namespace;
221
222         ptlrpc_abort_inflight(imp);
223
224 #if 0
225         obd_invalidate_import(obd, imp);
226 #endif
227
228         ldlm_namespace_cleanup(ns, LDLM_FL_LOCAL_ONLY | LDLM_FL_CANCEL);
229 }
230
231 void ptlrpc_handle_failed_import(struct obd_import *imp)
232 {
233         ENTRY;
234         if (!imp->imp_replayable) {
235                 CDEBUG(D_HA,
236                        "import %s@%s for %s not replayable, deactivating\n",
237                        imp->imp_target_uuid.uuid,
238                        imp->imp_connection->c_remote_uuid.uuid,
239                        imp->imp_obd->obd_name);
240                 ptlrpc_set_import_active(imp, 0);
241         }
242
243         ptlrpc_run_failed_import_upcall(imp);
244         EXIT;
245 }
246
247 void ptlrpc_request_handle_notconn(struct ptlrpc_request *failed_req)
248 {
249         int rc;
250         struct obd_import *imp= failed_req->rq_import;
251         unsigned long flags;
252         ENTRY;
253
254         CDEBUG(D_HA, "import %s of %s@%s abruptly disconnected: reconnecting\n",
255                imp->imp_obd->obd_name,
256                imp->imp_target_uuid.uuid,
257                imp->imp_connection->c_remote_uuid.uuid);
258
259         rc = ptlrpc_recover_import_no_retry(imp, NULL);
260
261         if (failed_req->rq_import_generation != imp->imp_generation) {
262                 spin_lock_irqsave (&failed_req->rq_lock, flags);
263                 failed_req->rq_err = 1;
264                 spin_unlock_irqrestore (&failed_req->rq_lock, flags);
265         }
266         else {
267                 ptlrpc_resend_req(failed_req);
268                 if (rc && rc != -EALREADY)
269                         ptlrpc_handle_failed_import(imp);
270                         
271         }
272         EXIT;
273 }
274
275 int ptlrpc_set_import_active(struct obd_import *imp, int active)
276 {
277         struct obd_device *obd = imp->imp_obd;
278         unsigned long flags;
279
280         LASSERT(obd);
281
282         /* When deactivating, mark import invalid, and abort in-flight
283          * requests. */
284         if (!active) {
285                 spin_lock_irqsave(&imp->imp_lock, flags);
286                 /* This is a bit of a hack, but invalidating replayable
287                  * imports makes a temporary reconnect failure into a much more
288                  * ugly -- and hard to remedy -- situation. */
289                 if (!imp->imp_replayable) {
290                         CDEBUG(D_HA, "setting import %s INVALID\n",
291                                imp->imp_target_uuid.uuid);
292                         imp->imp_invalid = 1;
293                 }
294                 imp->imp_generation++;
295                 spin_unlock_irqrestore(&imp->imp_lock, flags);
296                 ptlrpc_invalidate_import_state(imp);
297         }
298
299         /* When activating, mark import valid */
300         if (active) {
301                 CDEBUG(D_HA, "setting import %s VALID\n",
302                        imp->imp_target_uuid.uuid);
303                 spin_lock_irqsave(&imp->imp_lock, flags);
304                 imp->imp_invalid = 0;
305                 spin_unlock_irqrestore(&imp->imp_lock, flags);
306         }
307
308         if (obd->obd_observer)
309                 RETURN(obd_notify(obd->obd_observer, obd, active));
310
311         RETURN(0);
312 }
313
314 void ptlrpc_fail_import(struct obd_import *imp, int generation)
315 {
316         unsigned long flags;
317         int in_recovery = 0;
318         ENTRY;
319
320         LASSERT (!imp->imp_dlm_fake);
321
322         spin_lock_irqsave(&imp->imp_lock, flags);
323         if (imp->imp_state != LUSTRE_IMP_FULL) {
324                 in_recovery = 1;
325         } else {
326                 CDEBUG(D_HA, "%s: new state: DISCON\n", 
327                        imp->imp_client->cli_name);
328                 imp->imp_state = LUSTRE_IMP_DISCON;
329         }
330         spin_unlock_irqrestore(&imp->imp_lock, flags);
331
332         if (in_recovery) {
333                 EXIT;
334                 return;
335         }
336
337         ptlrpc_handle_failed_import(imp);
338         EXIT;
339 }
340
341 static int signal_completed_replay(struct obd_import *imp)
342 {
343         struct ptlrpc_request *req;
344         int rc;
345         ENTRY;
346
347         req = ptlrpc_prep_req(imp, OBD_PING, 0, NULL, NULL);
348         if (!req)
349                 RETURN(-ENOMEM);
350
351         req->rq_replen = lustre_msg_size(0, NULL);
352         req->rq_send_state = LUSTRE_IMP_REPLAY;
353         req->rq_reqmsg->flags |= MSG_LAST_REPLAY;
354         req->rq_timeout *= 3; 
355
356         rc = ptlrpc_queue_wait(req);
357
358         ptlrpc_req_finished(req);
359         RETURN(rc);
360 }
361
362 int ptlrpc_recover_import(struct obd_import *imp, char *new_uuid)
363 {
364         int rc;
365         ENTRY;
366         
367         rc = ptlrpc_recover_import_no_retry(imp, new_uuid);
368
369         if (rc && rc != -EALREADY) {
370                 unsigned long flags;
371                 CDEBUG(D_HA, "recovery of %s on %s failed (%d); restarting\n",
372                        imp->imp_target_uuid.uuid,
373                        new_uuid ? new_uuid :
374                        (char *)imp->imp_connection->c_remote_uuid.uuid, rc);
375                 spin_lock_irqsave(&imp->imp_lock, flags);
376                 imp->imp_state = LUSTRE_IMP_FULL;
377                 spin_unlock_irqrestore(&imp->imp_lock, flags);
378                 ptlrpc_fail_import(imp, imp->imp_generation);
379         }
380         RETURN(rc);
381 }
382
383 static int ptlrpc_recover_import_no_retry(struct obd_import *imp,
384                                           char *new_uuid)
385 {
386         int rc;
387         unsigned long flags;
388         int in_recovery = 0;
389         int was_invalid = 0;
390         ENTRY;
391
392         spin_lock_irqsave(&imp->imp_lock, flags);
393         if (imp->imp_state == LUSTRE_IMP_FULL) {
394                 CDEBUG(D_HA, "%s: new state: DISCON\n", 
395                        imp->imp_client->cli_name);
396                 imp->imp_state = LUSTRE_IMP_DISCON;
397         } 
398         
399         if (imp->imp_state != LUSTRE_IMP_DISCON) {
400                 in_recovery = 1;
401         } else if (imp->imp_invalid) {
402                 imp->imp_invalid = 0;
403                 was_invalid = 1;
404         }
405
406         spin_unlock_irqrestore(&imp->imp_lock, flags);
407
408         if (in_recovery == 1)
409                 RETURN(-EALREADY);
410
411         down(&imp->imp_recovery_sem);
412         /* If recovery happened while we waited, we're done. */
413         if (imp->imp_state == LUSTRE_IMP_FULL)
414                 GOTO(out, rc = 0);
415
416         LASSERT (imp->imp_state == LUSTRE_IMP_DISCON);
417
418         if (new_uuid) {
419                 struct ptlrpc_connection *conn;
420                 struct obd_uuid uuid;
421                 struct ptlrpc_peer peer;
422                 struct obd_export *dlmexp;
423
424                 obd_str2uuid(&uuid, new_uuid);
425                 if (ptlrpc_uuid_to_peer(&uuid, &peer)) {
426                         CERROR("no connection found for UUID %s\n", new_uuid);
427                         GOTO(out, rc = -EINVAL);
428                 }
429
430                 conn = ptlrpc_get_connection(&peer, &uuid);
431                 if (!conn)
432                         GOTO(out, rc = -ENOMEM);
433
434                 CDEBUG(D_HA, "switching import %s/%s from %s to %s\n",
435                        imp->imp_target_uuid.uuid, imp->imp_obd->obd_name,
436                        imp->imp_connection->c_remote_uuid.uuid,
437                        conn->c_remote_uuid.uuid);
438
439                 /* Switch the import's connection and the DLM export's
440                  * connection (which are almost certainly the same, but we
441                  * keep distinct refs just to make things clearer. I think. */
442                 if (imp->imp_connection)
443                         ptlrpc_put_connection(imp->imp_connection);
444                 /* We hand off the ref from ptlrpc_get_connection. */
445                 imp->imp_connection = conn;
446
447                 dlmexp = class_conn2export(&imp->imp_dlm_handle);
448                 if (dlmexp->exp_connection)
449                         ptlrpc_put_connection(dlmexp->exp_connection);
450                 dlmexp->exp_connection = ptlrpc_connection_addref(conn);
451                 class_export_put(dlmexp);
452
453         }
454
455  connect:
456         rc = ptlrpc_connect_import(imp);
457
458         if (rc < 0) {
459                 CERROR("failed to reconnect to %s@%s: %d\n",
460                        imp->imp_target_uuid.uuid,
461                        imp->imp_connection->c_remote_uuid.uuid, rc);
462                 GOTO(out, rc);
463         } 
464
465         if (imp->imp_state == LUSTRE_IMP_EVICTED) {
466                 CDEBUG(D_HA, "evicted from %s@%s; invalidating\n",
467                        imp->imp_target_uuid.uuid,
468                        imp->imp_connection->c_remote_uuid.uuid);
469                 ptlrpc_set_import_active(imp, 0);
470                 CDEBUG(D_HA, "%s: new state: RECOVER\n", 
471                        imp->imp_client->cli_name);
472                 imp->imp_state = LUSTRE_IMP_RECOVER;
473         } 
474         
475         if (imp->imp_state == LUSTRE_IMP_REPLAY) {
476                 CDEBUG(D_HA, "replay requested by %s\n",
477                        imp->imp_target_uuid.uuid);
478                 rc = ptlrpc_replay(imp);
479                 if (rc)
480                         GOTO(out, rc);
481
482                 rc = ldlm_replay_locks(imp);
483                 if (rc)
484                         GOTO(out, rc);
485
486                 rc = signal_completed_replay(imp);
487                 if (rc)
488                         GOTO(out, rc);
489                 CDEBUG(D_HA, "%s: new state: RECOVER\n", 
490                        imp->imp_client->cli_name);
491                 imp->imp_state = LUSTRE_IMP_RECOVER;
492         } 
493
494         if (imp->imp_state == LUSTRE_IMP_RECOVER) {
495                 CDEBUG(D_HA, "reconnected to %s@%s\n",
496                        imp->imp_target_uuid.uuid,
497                        imp->imp_connection->c_remote_uuid.uuid);
498
499                 ptlrpc_set_import_active(imp, 1);
500                 ptlrpc_resend(imp);
501                 spin_lock_irqsave(&imp->imp_lock, flags);
502                 CDEBUG(D_HA, "%s: new state: FULL\n", 
503                        imp->imp_client->cli_name);
504                 imp->imp_state = LUSTRE_IMP_FULL;
505                 spin_unlock_irqrestore(&imp->imp_lock, flags);
506                 ptlrpc_wake_delayed(imp);
507         } 
508
509
510         LASSERT(imp->imp_state == LUSTRE_IMP_FULL);
511
512  out:
513         if (rc != 0) {
514                 spin_lock_irqsave(&imp->imp_lock, flags);
515                 imp->imp_state = LUSTRE_IMP_DISCON;
516                 spin_unlock_irqrestore(&imp->imp_lock, flags);
517                 
518                 if (rc == -ENOTCONN) {
519                         CDEBUG(D_HA, "evicted/aborted by %s@%s during recovery;"
520                                "invalidating and reconnecting\n",
521                                imp->imp_target_uuid.uuid,
522                                imp->imp_connection->c_remote_uuid.uuid);
523                         GOTO(connect, -ENOTCONN);
524                 } else if (was_invalid) {
525                         ptlrpc_set_import_active(imp, 0);
526                 }
527         }
528         up(&imp->imp_recovery_sem);
529         RETURN(rc);
530 }
531
532 void ptlrpc_fail_export(struct obd_export *exp)
533 {
534         int rc, already_failed;
535         unsigned long flags;
536
537         spin_lock_irqsave(&exp->exp_lock, flags);
538         already_failed = exp->exp_failed;
539         exp->exp_failed = 1;
540         spin_unlock_irqrestore(&exp->exp_lock, flags);
541
542         if (already_failed) {
543                 CDEBUG(D_HA, "disconnecting dead export %p/%s; skipping\n",
544                        exp, exp->exp_client_uuid.uuid);
545                 return;
546         }
547
548         CDEBUG(D_HA, "disconnecting export %p/%s\n",
549                exp, exp->exp_client_uuid.uuid);
550
551         /* Most callers into obd_disconnect are removing their own reference
552          * (request, for example) in addition to the one from the hash table.
553          * We don't have such a reference here, so make one. */
554         class_export_get(exp);
555         rc = obd_disconnect(exp, 0);
556         if (rc)
557                 CERROR("disconnecting export %p failed: %d\n", exp, rc);
558 }