+ if (in_recovery == 1)
+ RETURN(-EALREADY);
+
+ rc = ptlrpc_connect_import(imp, new_uuid);
+ if (rc)
+ RETURN(rc);
+
+ CDEBUG(D_HA, "%s: recovery started, waiting\n",
+ imp->imp_target_uuid.uuid);
+
+ lwi = LWI_TIMEOUT(MAX(obd_timeout * HZ, 1), NULL, NULL);
+ rc = l_wait_event(imp->imp_recovery_waitq,
+ !ptlrpc_import_in_recovery(imp), &lwi);
+ CDEBUG(D_HA, "%s: recovery finished\n",
+ imp->imp_target_uuid.uuid);
+
+ RETURN(rc);
+}
+
+void ptlrpc_fail_export(struct obd_export *exp)
+{
+ int rc, already_failed;
+ unsigned long flags;
+
+ spin_lock_irqsave(&exp->exp_lock, flags);
+ already_failed = exp->exp_failed;
+ exp->exp_failed = 1;
+ spin_unlock_irqrestore(&exp->exp_lock, flags);
+
+ if (already_failed) {
+ CDEBUG(D_HA, "disconnecting dead export %p/%s; skipping\n",
+ exp, exp->exp_client_uuid.uuid);
+ return;
+ }
+
+ CDEBUG(D_HA, "disconnecting export %p/%s\n",
+ exp, exp->exp_client_uuid.uuid);
+
+ if (obd_dump_on_timeout)
+ portals_debug_dumplog();
+
+ /* Most callers into obd_disconnect are removing their own reference
+ * (request, for example) in addition to the one from the hash table.
+ * We don't have such a reference here, so make one. */
+ class_export_get(exp);
+ rc = obd_disconnect(exp, 0);
+ if (rc)
+ CERROR("disconnecting export %p failed: %d\n", exp, rc);