* be given to the handler if their payload is longer than the max. */
 int o2net_register_handler(u32 msg_type, u32 key, u32 max_len,
                           o2net_msg_handler_func *func, void *data,
+                          o2net_post_msg_handler_func *post_func,
                           struct list_head *unreg_list)
 {
        struct o2net_msg_handler *nmh = NULL;
 
        nmh->nh_func = func;
        nmh->nh_func_data = data;
+       nmh->nh_post_func = post_func;
        nmh->nh_msg_type = msg_type;
        nmh->nh_max_len = max_len;
        nmh->nh_key = key;
        int ret = 0, handler_status;
        enum  o2net_system_error syserr;
        struct o2net_msg_handler *nmh = NULL;
+       void *ret_data = NULL;
 
        msglog(hdr, "processing message\n");
 
        sc->sc_msg_type = be16_to_cpu(hdr->msg_type);
        handler_status = (nmh->nh_func)(hdr, sizeof(struct o2net_msg) +
                                             be16_to_cpu(hdr->data_len),
-                                       nmh->nh_func_data);
+                                       nmh->nh_func_data, &ret_data);
        do_gettimeofday(&sc->sc_tv_func_stop);
 
 out_respond:
        mlog(0, "sending handler status %d, syserr %d returned %d\n",
             handler_status, syserr, ret);
 
+       if (nmh) {
+               BUG_ON(ret_data != NULL && nmh->nh_post_func == NULL);
+               if (nmh->nh_post_func)
+                       (nmh->nh_post_func)(handler_status, nmh->nh_func_data,
+                                           ret_data);
+       }
+
 out:
        if (nmh)
                o2net_handler_put(nmh);
 
        __u8  buf[0];
 };
 
-typedef int (o2net_msg_handler_func)(struct o2net_msg *msg, u32 len, void *data);
+typedef int (o2net_msg_handler_func)(struct o2net_msg *msg, u32 len, void *data,
+                                    void **ret_data);
+typedef void (o2net_post_msg_handler_func)(int status, void *data,
+                                          void *ret_data);
 
 #define O2NET_MAX_PAYLOAD_BYTES  (4096 - sizeof(struct o2net_msg))
 
 
 int o2net_register_handler(u32 msg_type, u32 key, u32 max_len,
                           o2net_msg_handler_func *func, void *data,
+                          o2net_post_msg_handler_func *post_func,
                           struct list_head *unreg_list);
 void o2net_unregister_handler_list(struct list_head *list);
 
 
        u32                     nh_key;
        o2net_msg_handler_func  *nh_func;
        o2net_msg_handler_func  *nh_func_data;
+       o2net_post_msg_handler_func
+                               *nh_post_func;
        struct kref             nh_kref;
        struct list_head        nh_unregister_item;
 };
 
 
 
 
-int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data)
+int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data,
+                         void **ret_data)
 {
        int ret;
        unsigned int locklen;
 
 void dlm_lock_attach_lockres(struct dlm_lock *lock,
                             struct dlm_lock_resource *res);
 
-int dlm_create_lock_handler(struct o2net_msg *msg, u32 len, void *data);
-int dlm_convert_lock_handler(struct o2net_msg *msg, u32 len, void *data);
-int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data);
+int dlm_create_lock_handler(struct o2net_msg *msg, u32 len, void *data,
+                           void **ret_data);
+int dlm_convert_lock_handler(struct o2net_msg *msg, u32 len, void *data,
+                            void **ret_data);
+int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data,
+                         void **ret_data);
 
 void dlm_revert_pending_convert(struct dlm_lock_resource *res,
                                struct dlm_lock *lock);
 void dlm_revert_pending_lock(struct dlm_lock_resource *res,
                             struct dlm_lock *lock);
 
-int dlm_unlock_lock_handler(struct o2net_msg *msg, u32 len, void *data);
+int dlm_unlock_lock_handler(struct o2net_msg *msg, u32 len, void *data,
+                           void **ret_data);
 void dlm_commit_pending_cancel(struct dlm_lock_resource *res,
                               struct dlm_lock *lock);
 void dlm_commit_pending_unlock(struct dlm_lock_resource *res,
                             struct dlm_lock_resource *res);
 void __dlm_lockres_reserve_ast(struct dlm_lock_resource *res);
 
-int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data);
-int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data);
-int dlm_deref_lockres_handler(struct o2net_msg *msg, u32 len, void *data);
-int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data);
-int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data);
-int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data);
-int dlm_request_all_locks_handler(struct o2net_msg *msg, u32 len, void *data);
-int dlm_reco_data_done_handler(struct o2net_msg *msg, u32 len, void *data);
-int dlm_begin_reco_handler(struct o2net_msg *msg, u32 len, void *data);
-int dlm_finalize_reco_handler(struct o2net_msg *msg, u32 len, void *data);
+int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data,
+                              void **ret_data);
+int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data,
+                             void **ret_data);
+int dlm_deref_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
+                             void **ret_data);
+int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data,
+                               void **ret_data);
+int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
+                           void **ret_data);
+int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data,
+                              void **ret_data);
+int dlm_request_all_locks_handler(struct o2net_msg *msg, u32 len, void *data,
+                                 void **ret_data);
+int dlm_reco_data_done_handler(struct o2net_msg *msg, u32 len, void *data,
+                              void **ret_data);
+int dlm_begin_reco_handler(struct o2net_msg *msg, u32 len, void *data,
+                          void **ret_data);
+int dlm_finalize_reco_handler(struct o2net_msg *msg, u32 len, void *data,
+                             void **ret_data);
 int dlm_do_master_requery(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
                          u8 nodenum, u8 *real_master);
 
 
  * returns: DLM_NORMAL, DLM_IVLOCKID, DLM_BADARGS,
  *          status from __dlmconvert_master
  */
-int dlm_convert_lock_handler(struct o2net_msg *msg, u32 len, void *data)
+int dlm_convert_lock_handler(struct o2net_msg *msg, u32 len, void *data,
+                            void **ret_data)
 {
        struct dlm_ctxt *dlm = data;
        struct dlm_convert_lock *cnv = (struct dlm_convert_lock *)msg->buf;
 
 
 #define DLM_DOMAIN_BACKOFF_MS 200
 
-static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data);
-static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data);
-static int dlm_cancel_join_handler(struct o2net_msg *msg, u32 len, void *data);
-static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data);
+static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data,
+                                 void **ret_data);
+static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data,
+                                    void **ret_data);
+static int dlm_cancel_join_handler(struct o2net_msg *msg, u32 len, void *data,
+                                  void **ret_data);
+static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data,
+                                  void **ret_data);
 
 static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm);
 
        printk("\n");
 }
 
-static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data)
+static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data,
+                                  void **ret_data)
 {
        struct dlm_ctxt *dlm = data;
        unsigned int node;
 }
 EXPORT_SYMBOL_GPL(dlm_unregister_domain);
 
-static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data)
+static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data,
+                                 void **ret_data)
 {
        struct dlm_query_join_request *query;
        enum dlm_query_join_response response;
        return response;
 }
 
-static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data)
+static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data,
+                                    void **ret_data)
 {
        struct dlm_assert_joined *assert;
        struct dlm_ctxt *dlm = NULL;
        return 0;
 }
 
-static int dlm_cancel_join_handler(struct o2net_msg *msg, u32 len, void *data)
+static int dlm_cancel_join_handler(struct o2net_msg *msg, u32 len, void *data,
+                                  void **ret_data)
 {
        struct dlm_cancel_join *cancel;
        struct dlm_ctxt *dlm = NULL;
        status = o2net_register_handler(DLM_MASTER_REQUEST_MSG, dlm->key,
                                        sizeof(struct dlm_master_request),
                                        dlm_master_request_handler,
-                                       dlm, &dlm->dlm_domain_handlers);
+                                       dlm, NULL, &dlm->dlm_domain_handlers);
        if (status)
                goto bail;
 
        status = o2net_register_handler(DLM_ASSERT_MASTER_MSG, dlm->key,
                                        sizeof(struct dlm_assert_master),
                                        dlm_assert_master_handler,
-                                       dlm, &dlm->dlm_domain_handlers);
+                                       dlm, NULL, &dlm->dlm_domain_handlers);
        if (status)
                goto bail;
 
        status = o2net_register_handler(DLM_CREATE_LOCK_MSG, dlm->key,
                                        sizeof(struct dlm_create_lock),
                                        dlm_create_lock_handler,
-                                       dlm, &dlm->dlm_domain_handlers);
+                                       dlm, NULL, &dlm->dlm_domain_handlers);
        if (status)
                goto bail;
 
        status = o2net_register_handler(DLM_CONVERT_LOCK_MSG, dlm->key,
                                        DLM_CONVERT_LOCK_MAX_LEN,
                                        dlm_convert_lock_handler,
-                                       dlm, &dlm->dlm_domain_handlers);
+                                       dlm, NULL, &dlm->dlm_domain_handlers);
        if (status)
                goto bail;
 
        status = o2net_register_handler(DLM_UNLOCK_LOCK_MSG, dlm->key,
                                        DLM_UNLOCK_LOCK_MAX_LEN,
                                        dlm_unlock_lock_handler,
-                                       dlm, &dlm->dlm_domain_handlers);
+                                       dlm, NULL, &dlm->dlm_domain_handlers);
        if (status)
                goto bail;
 
        status = o2net_register_handler(DLM_PROXY_AST_MSG, dlm->key,
                                        DLM_PROXY_AST_MAX_LEN,
                                        dlm_proxy_ast_handler,
-                                       dlm, &dlm->dlm_domain_handlers);
+                                       dlm, NULL, &dlm->dlm_domain_handlers);
        if (status)
                goto bail;
 
        status = o2net_register_handler(DLM_EXIT_DOMAIN_MSG, dlm->key,
                                        sizeof(struct dlm_exit_domain),
                                        dlm_exit_domain_handler,
-                                       dlm, &dlm->dlm_domain_handlers);
+                                       dlm, NULL, &dlm->dlm_domain_handlers);
        if (status)
                goto bail;
 
        status = o2net_register_handler(DLM_DEREF_LOCKRES_MSG, dlm->key,
                                        sizeof(struct dlm_deref_lockres),
                                        dlm_deref_lockres_handler,
-                                       dlm, &dlm->dlm_domain_handlers);
+                                       dlm, NULL, &dlm->dlm_domain_handlers);
        if (status)
                goto bail;
 
        status = o2net_register_handler(DLM_MIGRATE_REQUEST_MSG, dlm->key,
                                        sizeof(struct dlm_migrate_request),
                                        dlm_migrate_request_handler,
-                                       dlm, &dlm->dlm_domain_handlers);
+                                       dlm, NULL, &dlm->dlm_domain_handlers);
        if (status)
                goto bail;
 
        status = o2net_register_handler(DLM_MIG_LOCKRES_MSG, dlm->key,
                                        DLM_MIG_LOCKRES_MAX_LEN,
                                        dlm_mig_lockres_handler,
-                                       dlm, &dlm->dlm_domain_handlers);
+                                       dlm, NULL, &dlm->dlm_domain_handlers);
        if (status)
                goto bail;
 
        status = o2net_register_handler(DLM_MASTER_REQUERY_MSG, dlm->key,
                                        sizeof(struct dlm_master_requery),
                                        dlm_master_requery_handler,
-                                       dlm, &dlm->dlm_domain_handlers);
+                                       dlm, NULL, &dlm->dlm_domain_handlers);
        if (status)
                goto bail;
 
        status = o2net_register_handler(DLM_LOCK_REQUEST_MSG, dlm->key,
                                        sizeof(struct dlm_lock_request),
                                        dlm_request_all_locks_handler,
-                                       dlm, &dlm->dlm_domain_handlers);
+                                       dlm, NULL, &dlm->dlm_domain_handlers);
        if (status)
                goto bail;
 
        status = o2net_register_handler(DLM_RECO_DATA_DONE_MSG, dlm->key,
                                        sizeof(struct dlm_reco_data_done),
                                        dlm_reco_data_done_handler,
-                                       dlm, &dlm->dlm_domain_handlers);
+                                       dlm, NULL, &dlm->dlm_domain_handlers);
        if (status)
                goto bail;
 
        status = o2net_register_handler(DLM_BEGIN_RECO_MSG, dlm->key,
                                        sizeof(struct dlm_begin_reco),
                                        dlm_begin_reco_handler,
-                                       dlm, &dlm->dlm_domain_handlers);
+                                       dlm, NULL, &dlm->dlm_domain_handlers);
        if (status)
                goto bail;
 
        status = o2net_register_handler(DLM_FINALIZE_RECO_MSG, dlm->key,
                                        sizeof(struct dlm_finalize_reco),
                                        dlm_finalize_reco_handler,
-                                       dlm, &dlm->dlm_domain_handlers);
+                                       dlm, NULL, &dlm->dlm_domain_handlers);
        if (status)
                goto bail;
 
        status = o2net_register_handler(DLM_QUERY_JOIN_MSG, DLM_MOD_KEY,
                                        sizeof(struct dlm_query_join_request),
                                        dlm_query_join_handler,
-                                       NULL, &dlm_join_handlers);
+                                       NULL, NULL, &dlm_join_handlers);
        if (status)
                goto bail;
 
        status = o2net_register_handler(DLM_ASSERT_JOINED_MSG, DLM_MOD_KEY,
                                        sizeof(struct dlm_assert_joined),
                                        dlm_assert_joined_handler,
-                                       NULL, &dlm_join_handlers);
+                                       NULL, NULL, &dlm_join_handlers);
        if (status)
                goto bail;
 
        status = o2net_register_handler(DLM_CANCEL_JOIN_MSG, DLM_MOD_KEY,
                                        sizeof(struct dlm_cancel_join),
                                        dlm_cancel_join_handler,
-                                       NULL, &dlm_join_handlers);
+                                       NULL, NULL, &dlm_join_handlers);
 
 bail:
        if (status < 0)
 
  *   held on exit:  none
  * returns: DLM_NORMAL, DLM_SYSERR, DLM_IVLOCKID, DLM_NOTQUEUED
  */
-int dlm_create_lock_handler(struct o2net_msg *msg, u32 len, void *data)
+int dlm_create_lock_handler(struct o2net_msg *msg, u32 len, void *data,
+                           void **ret_data)
 {
        struct dlm_ctxt *dlm = data;
        struct dlm_create_lock *create = (struct dlm_create_lock *)msg->buf;
 
  *
  * if possible, TRIM THIS DOWN!!!
  */
-int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data)
+int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data,
+                              void **ret_data)
 {
        u8 response = DLM_MASTER_RESP_MAYBE;
        struct dlm_ctxt *dlm = data;
  *
  * if possible, TRIM THIS DOWN!!!
  */
-int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data)
+int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data,
+                             void **ret_data)
 {
        struct dlm_ctxt *dlm = data;
        struct dlm_master_list_entry *mle = NULL;
        return ret;
 }
 
-int dlm_deref_lockres_handler(struct o2net_msg *msg, u32 len, void *data)
+int dlm_deref_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
+                             void **ret_data)
 {
        struct dlm_ctxt *dlm = data;
        struct dlm_deref_lockres *deref = (struct dlm_deref_lockres *)msg->buf;
  * we will have no mle in the list to start with.  now we can add an mle for
  * the migration and this should be the only one found for those scanning the
  * list.  */
-int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data)
+int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data,
+                               void **ret_data)
 {
        struct dlm_ctxt *dlm = data;
        struct dlm_lock_resource *res = NULL;
 
 
 }
 
-int dlm_request_all_locks_handler(struct o2net_msg *msg, u32 len, void *data)
+int dlm_request_all_locks_handler(struct o2net_msg *msg, u32 len, void *data,
+                                 void **ret_data)
 {
        struct dlm_ctxt *dlm = data;
        struct dlm_lock_request *lr = (struct dlm_lock_request *)msg->buf;
 }
 
 
-int dlm_reco_data_done_handler(struct o2net_msg *msg, u32 len, void *data)
+int dlm_reco_data_done_handler(struct o2net_msg *msg, u32 len, void *data,
+                              void **ret_data)
 {
        struct dlm_ctxt *dlm = data;
        struct dlm_reco_data_done *done = (struct dlm_reco_data_done *)msg->buf;
  * do we spin?  returning an error only delays the problem really
  */
 
-int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data)
+int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
+                           void **ret_data)
 {
        struct dlm_ctxt *dlm = data;
        struct dlm_migratable_lockres *mres =
 /* this function cannot error, so unless the sending
  * or receiving of the message failed, the owner can
  * be trusted */
-int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data)
+int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data,
+                              void **ret_data)
 {
        struct dlm_ctxt *dlm = data;
        struct dlm_master_requery *req = (struct dlm_master_requery *)msg->buf;
        return ret;
 }
 
-int dlm_begin_reco_handler(struct o2net_msg *msg, u32 len, void *data)
+int dlm_begin_reco_handler(struct o2net_msg *msg, u32 len, void *data,
+                          void **ret_data)
 {
        struct dlm_ctxt *dlm = data;
        struct dlm_begin_reco *br = (struct dlm_begin_reco *)msg->buf;
        return ret;
 }
 
-int dlm_finalize_reco_handler(struct o2net_msg *msg, u32 len, void *data)
+int dlm_finalize_reco_handler(struct o2net_msg *msg, u32 len, void *data,
+                             void **ret_data)
 {
        struct dlm_ctxt *dlm = data;
        struct dlm_finalize_reco *fr = (struct dlm_finalize_reco *)msg->buf;
 
  * returns: DLM_NORMAL, DLM_BADARGS, DLM_IVLOCKID,
  *          return value from dlmunlock_master
  */
-int dlm_unlock_lock_handler(struct o2net_msg *msg, u32 len, void *data)
+int dlm_unlock_lock_handler(struct o2net_msg *msg, u32 len, void *data,
+                           void **ret_data)
 {
        struct dlm_ctxt *dlm = data;
        struct dlm_unlock_lock *unlock = (struct dlm_unlock_lock *)msg->buf;
 
 
 static int ocfs2_handle_response_message(struct o2net_msg *msg,
                                         u32 len,
-                                        void *data)
+                                        void *data, void **ret_data)
 {
        unsigned int response_id, node_num;
        int response_status;
 
 static int ocfs2_handle_vote_message(struct o2net_msg *msg,
                                     u32 len,
-                                    void *data)
+                                    void *data, void **ret_data)
 {
        int status;
        struct ocfs2_super *osb = data;
                                        osb->net_key,
                                        sizeof(struct ocfs2_response_msg),
                                        ocfs2_handle_response_message,
-                                       osb, &osb->osb_net_handlers);
+                                       osb, NULL, &osb->osb_net_handlers);
        if (status) {
                mlog_errno(status);
                goto bail;
                                        osb->net_key,
                                        sizeof(struct ocfs2_vote_msg),
                                        ocfs2_handle_vote_message,
-                                       osb, &osb->osb_net_handlers);
+                                       osb, NULL, &osb->osb_net_handlers);
        if (status) {
                mlog_errno(status);
                goto bail;