/*---------------------------------------------------------------------------*/ void xio_context_destroy(struct xio_context *ctx) { int i; xio_observable_notify_all_observers(&ctx->observable, XIO_CONTEXT_EVENT_CLOSE, NULL); xio_observable_unreg_all_observers(&ctx->observable); for (i = 0; i < XIO_STAT_LAST; i++) if (ctx->stats.name[i]) kfree(ctx->stats.name[i]); xio_workqueue_destroy(ctx->workqueue); /* can free only xio created loop */ if (ctx->flags != XIO_LOOP_USER_LOOP) xio_ev_loop_destroy(ctx->ev_loop); ctx->ev_loop = NULL; if (ctx->ctx_dentry) { debugfs_remove_recursive(ctx->ctx_dentry); ctx->ctx_dentry = NULL; } kfree(ctx); }
/*---------------------------------------------------------------------------*/ void xio_destroy_context_continue(struct work_struct *work) { xio_work_handle_t *xio_work; struct xio_context *ctx; int i; xio_work = container_of(work, xio_work_handle_t, work); ctx = container_of(xio_work, struct xio_context, destroy_ctx_work); if (ctx->run_private) ERROR_LOG("not all observers finished! run_private=%d\n", ctx->run_private); xio_observable_notify_all_observers(&ctx->observable, XIO_CONTEXT_EVENT_POST_CLOSE, NULL); if (!xio_observable_is_empty(&ctx->observable)) ERROR_LOG("context destroy: observers leak - %p\n", ctx); xio_observable_unreg_all_observers(&ctx->observable); for (i = 0; i < XIO_STAT_LAST; i++) kfree(ctx->stats.name[i]); xio_workqueue_destroy(ctx->workqueue); xio_objpool_destroy(ctx->msg_pool); /* can free only xio created loop */ if (ctx->flags != XIO_LOOP_USER_LOOP) xio_ev_loop_destroy(ctx->ev_loop); ctx->ev_loop = NULL; XIO_OBSERVABLE_DESTROY(&ctx->observable); xio_ctx_task_pools_destroy(ctx); if (ctx->mempool) { xio_mempool_destroy(ctx->mempool); ctx->mempool = NULL; } kfree(ctx); }
void xio_context_destroy(struct xio_context *ctx) { int found; found = xio_idr_lookup_uobj(usr_idr, ctx); if (found) { xio_idr_remove_uobj(usr_idr, ctx); } else { ERROR_LOG("context not found:%p\n", ctx); xio_set_error(XIO_E_USER_OBJ_NOT_FOUND); return; } ctx->run_private = 0; xio_observable_notify_all_observers(&ctx->observable, XIO_CONTEXT_EVENT_CLOSE, NULL); /* allow internally to run the loop for final cleanup */ if (ctx->run_private) xio_context_run_loop(ctx); if (ctx->run_private == 0) xio_destroy_context_continue(&ctx->destroy_ctx_work.work); }
/*---------------------------------------------------------------------------*/ int xio_unbind(struct xio_server *server) { int retval = 0; int found; if (!server) return -1; found = xio_idr_lookup_uobj(usr_idr, server); if (found) { xio_idr_remove_uobj(usr_idr, server); } else { ERROR_LOG("server not found:%p\n", server); xio_set_error(XIO_E_USER_OBJ_NOT_FOUND); return -1; } /* notify all observers that the server wishes to exit */ xio_observable_notify_all_observers(&server->nexus_observable, XIO_SERVER_EVENT_CLOSE, NULL); kref_put(&server->kref, xio_server_destroy); return retval; }