X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fobdclass%2Fgenops.c;h=a74ee1844b542b608693d5e956f12b60d9dad1f2;hb=41ab260642f4923106da3567d7c75e1ca3c61ea4;hp=615b2f9dda2a64ebc56de3a8841e15d732893b6a;hpb=b401ba0c214b184424146dda994470aa3c4356c9;p=fs%2Flustre-release.git diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c index 615b2f9..a74ee18 100644 --- a/lustre/obdclass/genops.c +++ b/lustre/obdclass/genops.c @@ -723,6 +723,7 @@ static void class_export_destroy(struct obd_export *exp) ptlrpc_put_connection_superhack(exp->exp_connection); LASSERT(list_empty(&exp->exp_outstanding_replies)); + LASSERT(list_empty(&exp->exp_uncommitted_replies)); LASSERT(list_empty(&exp->exp_req_replay_queue)); LASSERT(list_empty(&exp->exp_queued_rpc)); obd_destroy_export(exp); @@ -781,6 +782,8 @@ struct obd_export *class_new_export(struct obd_device *obd, atomic_set(&export->exp_rpc_count, 0); export->exp_obd = obd; CFS_INIT_LIST_HEAD(&export->exp_outstanding_replies); + spin_lock_init(&export->exp_uncommitted_replies_lock); + CFS_INIT_LIST_HEAD(&export->exp_uncommitted_replies); CFS_INIT_LIST_HEAD(&export->exp_req_replay_queue); CFS_INIT_LIST_HEAD(&export->exp_handle.h_link); CFS_INIT_LIST_HEAD(&export->exp_queued_rpc); @@ -837,6 +840,15 @@ void class_unlink_export(struct obd_export *exp) exp->exp_obd->obd_num_exports--; spin_unlock(&exp->exp_obd->obd_dev_lock); + /* Keep these counter valid always */ + spin_lock_bh(&exp->exp_obd->obd_processing_task_lock); + if (exp->exp_delayed) + exp->exp_obd->obd_delayed_clients--; + else if (exp->exp_in_recovery) + exp->exp_obd->obd_recoverable_clients--; + else if (exp->exp_obd->obd_recovering) + exp->exp_obd->obd_max_recoverable_clients--; + spin_unlock_bh(&exp->exp_obd->obd_processing_task_lock); class_export_put(exp); } EXPORT_SYMBOL(class_unlink_export); @@ -1027,10 +1039,12 @@ void class_export_recovery_cleanup(struct obd_export *exp) spin_unlock_bh(&obd->obd_processing_task_lock); } -/* 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; @@ -1045,25 +1059,27 @@ int class_disconnect(struct obd_export *export) 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); + if (already_disconnected) { + LASSERT(hlist_unhashed(&export->exp_nid_hash)); + 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_export_recovery_cleanup(export); class_unlink_export(export); +no_disconn: class_export_put(export); RETURN(0); } @@ -1072,14 +1088,14 @@ static void class_disconnect_export_list(struct list_head *list, 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); @@ -1098,22 +1114,16 @@ static void class_disconnect_export_list(struct list_head *list, 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 "CFS_TIME_T"\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); } EXIT; @@ -1125,9 +1135,10 @@ void class_disconnect_exports(struct obd_device *obd) ENTRY; /* Move all of the exports from obd_exports to a work list, en masse. */ + CFS_INIT_LIST_HEAD(&work_list); spin_lock(&obd->obd_dev_lock); - list_add(&work_list, &obd->obd_exports); - list_del_init(&obd->obd_exports); + list_splice_init(&obd->obd_exports, &work_list); + list_splice_init(&obd->obd_delayed_exports, &work_list); spin_unlock(&obd->obd_dev_lock); if (!list_empty(&work_list)) { @@ -1144,31 +1155,30 @@ EXPORT_SYMBOL(class_disconnect_exports); /* Remove exports that have not completed recovery. */ -int class_disconnect_stale_exports(struct obd_device *obd, - int (*test_export)(struct obd_export *), - enum obd_option flags) +void class_disconnect_stale_exports(struct obd_device *obd, + int (*test_export)(struct obd_export *), + enum obd_option flags) { struct list_head work_list; struct list_head *pos, *n; struct obd_export *exp; - int cnt = 0; ENTRY; CFS_INIT_LIST_HEAD(&work_list); spin_lock(&obd->obd_dev_lock); + obd->obd_stale_clients = 0; list_for_each_safe(pos, n, &obd->obd_exports) { exp = list_entry(pos, struct obd_export, exp_obd_chain); if (test_export(exp)) continue; - list_del(&exp->exp_obd_chain); - list_add(&exp->exp_obd_chain, &work_list); + list_move(&exp->exp_obd_chain, &work_list); /* don't count self-export as client */ if (obd_uuid_equals(&exp->exp_client_uuid, &exp->exp_obd->obd_uuid)) continue; - cnt++; + obd->obd_stale_clients++; CDEBUG(D_ERROR, "%s: disconnect stale client %s@%s\n", obd->obd_name, exp->exp_client_uuid.uuid, exp->exp_connection == NULL ? "" : @@ -1176,10 +1186,11 @@ int class_disconnect_stale_exports(struct obd_device *obd, } spin_unlock(&obd->obd_dev_lock); - CDEBUG(D_ERROR, "%s: disconnecting %d stale clients\n", - obd->obd_name, cnt); + CDEBUG(D_HA, "%s: disconnecting %d stale clients\n", obd->obd_name, + obd->obd_stale_clients); + class_disconnect_export_list(&work_list, flags); - RETURN(cnt); + EXIT; } EXPORT_SYMBOL(class_disconnect_stale_exports); @@ -1371,6 +1382,7 @@ static void obd_zombie_export_add(struct obd_export *exp) { * Add import to the obd_zombe thread and notify it. */ static void obd_zombie_import_add(struct obd_import *imp) { + LASSERT(imp->imp_sec == NULL); spin_lock(&obd_zombie_impexp_lock); LASSERT(list_empty(&imp->imp_zombie_chain)); list_add(&imp->imp_zombie_chain, &obd_zombie_imports);