if (!cli->cl_conn_count) {
CERROR("disconnecting disconnected device (%s)\n",
obd->obd_name);
- GOTO(out_sem, rc = -EINVAL);
+ GOTO(out_disconnect, rc = -EINVAL);
}
cli->cl_conn_count--;
if (cli->cl_conn_count)
- GOTO(out_no_disconnect, rc = 0);
+ GOTO(out_disconnect, rc = 0);
/* Mark import deactivated now, so we don't try to reconnect if any
* of the cleanup RPCs fails (e.g. ldlm cancel, etc). We don't
cli->cl_import = NULL;
EXIT;
- out_no_disconnect:
+
+ out_disconnect:
+ /* use server style - class_disconnect should be always called for
+ * o_disconnect */
err = class_disconnect(exp);
if (!rc && err)
rc = err;
- out_sem:
+
up_write(&cli->cl_sem);
if (to_be_freed)
ldlm_namespace_free_post(to_be_freed);
}
EXPORT_SYMBOL(class_connect);
-/* This function removes two references from the export: one for the
- * hash entry and one for the export pointer passed in. The export
- * pointer passed to this function is destroyed should not be used
- * again. */
+/* This function removes 1-3 references from the export:
+ * 1 - for export pointer passed
+ * and if disconnect really need
+ * 2 - removing from hash
+ * 3 - in client_unlink_export
+ * The export pointer passed to this function can destroyed */
int class_disconnect(struct obd_export *export)
{
int already_disconnected;
spin_lock(&export->exp_lock);
already_disconnected = export->exp_disconnected;
export->exp_disconnected = 1;
-
- if (!hlist_unhashed(&export->exp_nid_hash))
- lustre_hash_del(export->exp_obd->obd_nid_hash,
- &export->exp_connection->c_peer.nid,
- &export->exp_nid_hash);
-
spin_unlock(&export->exp_lock);
+
/* class_cleanup(), abort_recovery(), and class_fail_export()
* all end up in here, and if any of them race we shouldn't
* call extra class_export_puts(). */
if (already_disconnected)
- RETURN(0);
+ GOTO(no_disconn, already_disconnected);
CDEBUG(D_IOCTL, "disconnect: cookie "LPX64"\n",
export->exp_handle.h_cookie);
+
+ if (!hlist_unhashed(&export->exp_nid_hash))
+ lustre_hash_del(export->exp_obd->obd_nid_hash,
+ &export->exp_connection->c_peer.nid,
+ &export->exp_nid_hash);
+
class_unlink_export(export);
+
+no_disconn:
class_export_put(export);
RETURN(0);
}
enum obd_option flags)
{
int rc;
- struct lustre_handle fake_conn;
- struct obd_export *fake_exp, *exp;
+ struct obd_export *exp;
ENTRY;
/* It's possible that an export may disconnect itself, but
* nothing else will be added to this list. */
while (!list_empty(list)) {
exp = list_entry(list->next, struct obd_export, exp_obd_chain);
+ /* need for safe call CDEBUG after obd_disconnect */
class_export_get(exp);
spin_lock(&exp->exp_lock);
continue;
}
- fake_conn.cookie = exp->exp_handle.h_cookie;
- fake_exp = class_conn2export(&fake_conn);
- if (!fake_exp) {
- class_export_put(exp);
- continue;
- }
-
- spin_lock(&fake_exp->exp_lock);
- fake_exp->exp_flags = flags;
- spin_unlock(&fake_exp->exp_lock);
-
+ class_export_get(exp);
CDEBUG(D_HA, "%s: disconnecting export at %s (%p), "
"last request at %ld\n",
exp->exp_obd->obd_name, obd_export_nid2str(exp),
exp, exp->exp_last_request_time);
- rc = obd_disconnect(fake_exp);
+
+ /* release one export reference anyway */
+ rc = obd_disconnect(exp);
CDEBUG(D_HA, "disconnected export at %s (%p): rc %d\n",
obd_export_nid2str(exp), exp, rc);
class_export_put(exp);