Whamcloud - gitweb
r=zab,phil
[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         obd_invalidate_import(obd, imp);
225
226         ldlm_namespace_cleanup(ns, LDLM_FL_LOCAL_ONLY | LDLM_FL_CANCEL);
227 }
228
229 void ptlrpc_handle_failed_import(struct obd_import *imp)
230 {
231         ENTRY;
232         if (!imp->imp_replayable) {
233                 CDEBUG(D_HA,
234                        "import %s@%s for %s not replayable, deactivating\n",
235                        imp->imp_target_uuid.uuid,
236                        imp->imp_connection->c_remote_uuid.uuid,
237                        imp->imp_obd->obd_name);
238                 ptlrpc_set_import_active(imp, 0);
239         }
240
241         ptlrpc_run_failed_import_upcall(imp);
242         EXIT;
243 }
244
245 void ptlrpc_request_handle_notconn(struct ptlrpc_request *failed_req)
246 {
247         int rc;
248         struct obd_import *imp= failed_req->rq_import;
249         unsigned long flags;
250         ENTRY;
251
252         CDEBUG(D_HA, "import %s of %s@%s abruptly disconnected: reconnecting\n",
253                imp->imp_obd->obd_name,
254                imp->imp_target_uuid.uuid,
255                imp->imp_connection->c_remote_uuid.uuid);
256
257         rc = ptlrpc_recover_import_no_retry(imp, NULL);
258
259         if (failed_req->rq_import_generation != imp->imp_generation) {
260                 spin_lock_irqsave (&failed_req->rq_lock, flags);
261                 failed_req->rq_err = 1;
262                 spin_unlock_irqrestore (&failed_req->rq_lock, flags);
263         }
264         else {
265                 ptlrpc_resend_req(failed_req);
266                 if (rc && rc != -EALREADY)
267                         ptlrpc_handle_failed_import(imp);
268                         
269         }
270         EXIT;
271 }
272
273 int ptlrpc_set_import_active(struct obd_import *imp, int active)
274 {
275         struct obd_device *obd = imp->imp_obd;
276         unsigned long flags;
277
278         LASSERT(obd);
279
280         /* When deactivating, mark import invalid, and abort in-flight
281          * requests. */
282         if (!active) {
283                 spin_lock_irqsave(&imp->imp_lock, flags);
284                 /* This is a bit of a hack, but invalidating replayable
285                  * imports makes a temporary reconnect failure into a much more
286                  * ugly -- and hard to remedy -- situation. */
287                 if (!imp->imp_replayable) {
288                         CDEBUG(D_HA, "setting import %s INVALID\n",
289                                imp->imp_target_uuid.uuid);
290                         imp->imp_invalid = 1;
291                 }
292                 imp->imp_generation++;
293                 spin_unlock_irqrestore(&imp->imp_lock, flags);
294                 ptlrpc_invalidate_import_state(imp);
295         }
296
297         /* When activating, mark import valid */
298         if (active) {
299                 CDEBUG(D_HA, "setting import %s VALID\n",
300                        imp->imp_target_uuid.uuid);
301                 spin_lock_irqsave(&imp->imp_lock, flags);
302                 imp->imp_invalid = 0;
303                 spin_unlock_irqrestore(&imp->imp_lock, flags);
304         }
305
306         if (obd->obd_observer)
307                 RETURN(obd_notify(obd->obd_observer, obd, active));
308
309         RETURN(0);
310 }
311
312 void ptlrpc_fail_import(struct obd_import *imp, int generation)
313 {
314         unsigned long flags;
315         int in_recovery = 0;
316         ENTRY;
317
318         LASSERT (!imp->imp_dlm_fake);
319
320         spin_lock_irqsave(&imp->imp_lock, flags);
321         if (imp->imp_state != LUSTRE_IMP_FULL) {
322                 in_recovery = 1;
323         } else {
324                 CDEBUG(D_HA, "%s: new state: DISCON\n", 
325                        imp->imp_client->cli_name);
326                 imp->imp_state = LUSTRE_IMP_DISCON;
327         }
328         spin_unlock_irqrestore(&imp->imp_lock, flags);
329
330         if (in_recovery) {
331                 EXIT;
332                 return;
333         }
334
335         ptlrpc_handle_failed_import(imp);
336         EXIT;
337 }
338
339 static int signal_completed_replay(struct obd_import *imp)
340 {
341         struct ptlrpc_request *req;
342         int rc;
343         ENTRY;
344
345         req = ptlrpc_prep_req(imp, OBD_PING, 0, NULL, NULL);
346         if (!req)
347                 RETURN(-ENOMEM);
348
349         req->rq_replen = lustre_msg_size(0, NULL);
350         req->rq_send_state = LUSTRE_IMP_REPLAY;
351         req->rq_reqmsg->flags |= MSG_LAST_REPLAY;
352         req->rq_timeout *= 3; 
353
354         rc = ptlrpc_queue_wait(req);
355
356         ptlrpc_req_finished(req);
357         RETURN(rc);
358 }
359
360 int ptlrpc_recover_import(struct obd_import *imp, char *new_uuid)
361 {
362         int rc;
363         ENTRY;
364         
365         rc = ptlrpc_recover_import_no_retry(imp, new_uuid);
366
367         if (rc && rc != -EALREADY) {
368                 unsigned long flags;
369                 CDEBUG(D_HA, "recovery of %s on %s failed (%d); restarting\n",
370                        imp->imp_target_uuid.uuid,
371                        new_uuid ? new_uuid :
372                        (char *)imp->imp_connection->c_remote_uuid.uuid, rc);
373                 spin_lock_irqsave(&imp->imp_lock, flags);
374                 imp->imp_state = LUSTRE_IMP_FULL;
375                 spin_unlock_irqrestore(&imp->imp_lock, flags);
376                 ptlrpc_fail_import(imp, imp->imp_generation);
377         }
378         RETURN(rc);
379 }
380
381 static int ptlrpc_recover_import_no_retry(struct obd_import *imp,
382                                           char *new_uuid)
383 {
384         int rc;
385         unsigned long flags;
386         int in_recovery = 0;
387         int was_invalid = 0;
388         ENTRY;
389
390         spin_lock_irqsave(&imp->imp_lock, flags);
391         if (imp->imp_state == LUSTRE_IMP_FULL) {
392                 CDEBUG(D_HA, "%s: new state: DISCON\n", 
393                        imp->imp_client->cli_name);
394                 imp->imp_state = LUSTRE_IMP_DISCON;
395         } 
396         
397         if (imp->imp_state != LUSTRE_IMP_DISCON) {
398                 in_recovery = 1;
399         } else if (imp->imp_invalid) {
400                 imp->imp_invalid = 0;
401                 was_invalid = 1;
402         }
403
404         spin_unlock_irqrestore(&imp->imp_lock, flags);
405
406         if (in_recovery == 1)
407                 RETURN(-EALREADY);
408
409         down(&imp->imp_recovery_sem);
410         /* If recovery happened while we waited, we're done. */
411         if (imp->imp_state == LUSTRE_IMP_FULL)
412                 GOTO(out, rc = 0);
413
414         LASSERT (imp->imp_state == LUSTRE_IMP_DISCON);
415
416         if (new_uuid) {
417                 struct ptlrpc_connection *conn;
418                 struct obd_uuid uuid;
419                 struct ptlrpc_peer peer;
420                 struct obd_export *dlmexp;
421
422                 obd_str2uuid(&uuid, new_uuid);
423                 if (ptlrpc_uuid_to_peer(&uuid, &peer)) {
424                         CERROR("no connection found for UUID %s\n", new_uuid);
425                         GOTO(out, rc = -EINVAL);
426                 }
427
428                 conn = ptlrpc_get_connection(&peer, &uuid);
429                 if (!conn)
430                         GOTO(out, rc = -ENOMEM);
431
432                 CDEBUG(D_HA, "switching import %s/%s from %s to %s\n",
433                        imp->imp_target_uuid.uuid, imp->imp_obd->obd_name,
434                        imp->imp_connection->c_remote_uuid.uuid,
435                        conn->c_remote_uuid.uuid);
436
437                 /* Switch the import's connection and the DLM export's
438                  * connection (which are almost certainly the same, but we
439                  * keep distinct refs just to make things clearer. I think. */
440                 if (imp->imp_connection)
441                         ptlrpc_put_connection(imp->imp_connection);
442                 /* We hand off the ref from ptlrpc_get_connection. */
443                 imp->imp_connection = conn;
444
445                 dlmexp = class_conn2export(&imp->imp_dlm_handle);
446                 if (dlmexp->exp_connection)
447                         ptlrpc_put_connection(dlmexp->exp_connection);
448                 dlmexp->exp_connection = ptlrpc_connection_addref(conn);
449                 class_export_put(dlmexp);
450
451         }
452
453  connect:
454         rc = ptlrpc_connect_import(imp);
455
456         if (rc < 0) {
457                 CERROR("failed to reconnect to %s@%s: %d\n",
458                        imp->imp_target_uuid.uuid,
459                        imp->imp_connection->c_remote_uuid.uuid, rc);
460                 GOTO(out, rc);
461         } 
462
463         if (imp->imp_state == LUSTRE_IMP_EVICTED) {
464                 CDEBUG(D_HA, "evicted from %s@%s; invalidating\n",
465                        imp->imp_target_uuid.uuid,
466                        imp->imp_connection->c_remote_uuid.uuid);
467                 ptlrpc_set_import_active(imp, 0);
468                 CDEBUG(D_HA, "%s: new state: RECOVER\n", 
469                        imp->imp_client->cli_name);
470                 imp->imp_state = LUSTRE_IMP_RECOVER;
471         } 
472         
473         if (imp->imp_state == LUSTRE_IMP_REPLAY) {
474                 CDEBUG(D_HA, "replay requested by %s\n",
475                        imp->imp_target_uuid.uuid);
476                 rc = ptlrpc_replay(imp);
477                 if (rc)
478                         GOTO(out, rc);
479
480                 rc = ldlm_replay_locks(imp);
481                 if (rc)
482                         GOTO(out, rc);
483
484                 rc = signal_completed_replay(imp);
485                 if (rc)
486                         GOTO(out, rc);
487                 CDEBUG(D_HA, "%s: new state: RECOVER\n", 
488                        imp->imp_client->cli_name);
489                 imp->imp_state = LUSTRE_IMP_RECOVER;
490         } 
491
492         if (imp->imp_state == LUSTRE_IMP_RECOVER) {
493                 CDEBUG(D_HA, "reconnected to %s@%s\n",
494                        imp->imp_target_uuid.uuid,
495                        imp->imp_connection->c_remote_uuid.uuid);
496
497                 ptlrpc_set_import_active(imp, 1);
498                 ptlrpc_resend(imp);
499                 spin_lock_irqsave(&imp->imp_lock, flags);
500                 CDEBUG(D_HA, "%s: new state: FULL\n", 
501                        imp->imp_client->cli_name);
502                 imp->imp_state = LUSTRE_IMP_FULL;
503                 spin_unlock_irqrestore(&imp->imp_lock, flags);
504                 ptlrpc_wake_delayed(imp);
505         } 
506
507
508         LASSERT(imp->imp_state == LUSTRE_IMP_FULL);
509
510  out:
511         if (rc != 0) {
512                 spin_lock_irqsave(&imp->imp_lock, flags);
513                 imp->imp_state = LUSTRE_IMP_DISCON;
514                 spin_unlock_irqrestore(&imp->imp_lock, flags);
515                 
516                 if (rc == -ENOTCONN) {
517                         CDEBUG(D_HA, "evicted/aborted by %s@%s during recovery;"
518                                "invalidating and reconnecting\n",
519                                imp->imp_target_uuid.uuid,
520                                imp->imp_connection->c_remote_uuid.uuid);
521                         GOTO(connect, -ENOTCONN);
522                 } else if (was_invalid) {
523                         ptlrpc_set_import_active(imp, 0);
524                 }
525         }
526         up(&imp->imp_recovery_sem);
527         RETURN(rc);
528 }
529
530 void ptlrpc_fail_export(struct obd_export *exp)
531 {
532         int rc, already_failed;
533         unsigned long flags;
534
535         spin_lock_irqsave(&exp->exp_lock, flags);
536         already_failed = exp->exp_failed;
537         exp->exp_failed = 1;
538         spin_unlock_irqrestore(&exp->exp_lock, flags);
539
540         if (already_failed) {
541                 CDEBUG(D_HA, "disconnecting dead export %p/%s; skipping\n",
542                        exp, exp->exp_client_uuid.uuid);
543                 return;
544         }
545
546         CDEBUG(D_HA, "disconnecting export %p/%s\n",
547                exp, exp->exp_client_uuid.uuid);
548
549         /* Most callers into obd_disconnect are removing their own reference
550          * (request, for example) in addition to the one from the hash table.
551          * We don't have such a reference here, so make one. */
552         class_export_get(exp);
553         rc = obd_disconnect(exp, 0);
554         if (rc)
555                 CERROR("disconnecting export %p failed: %d\n", exp, rc);
556 }