diff --git a/accel-pptpd/ctrl/l2tp/l2tp.c b/accel-pptpd/ctrl/l2tp/l2tp.c index 29961272891c43c7cb7af1c50c4694c54595cd43..2a7687e1f04b7adb0a040a7c9297c4aef94ad100 100644 --- a/accel-pptpd/ctrl/l2tp/l2tp.c +++ b/accel-pptpd/ctrl/l2tp/l2tp.c @@ -137,7 +137,7 @@ static void l2tp_disconnect(struct l2tp_conn_t *conn) _free(conn->ctrl.calling_station_id); _free(conn->ctrl.called_station_id); - + mempool_free(conn); } @@ -333,6 +333,7 @@ static int l2tp_connect(struct l2tp_conn_t *conn) pppox_addr.pppol2tp.d_tunnel = conn->peer_tid; pppox_addr.pppol2tp.d_session = conn->peer_sid; + l2tp_nl_delete_tunnel(conn->tid); l2tp_nl_create_tunnel(conn->hnd.fd, conn->tid, conn->peer_tid); l2tp_nl_create_session(conn->tid, conn->sid, conn->peer_sid); @@ -420,7 +421,8 @@ static int l2tp_send(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack) list_add_tail(&pack->entry, &conn->send_queue); if (!conn->rtimeout_timer.tpd) triton_timer_add(&conn->ctx, &conn->rtimeout_timer, 0); - } + } else + l2tp_packet_free(pack); return 0; @@ -792,8 +794,6 @@ static int l2tp_conn_read(struct triton_md_handler_t *h) struct l2tp_attr_t *msg_type; while (1) { - pack = NULL; - if (l2tp_recv(h->fd, &pack)) return 0; @@ -923,8 +923,6 @@ static int l2tp_udp_read(struct triton_md_handler_t *h) struct l2tp_attr_t *msg_type; while (1) { - pack = NULL; - if (l2tp_recv(h->fd, &pack)) break; diff --git a/accel-pptpd/ctrl/l2tp/netlink.c b/accel-pptpd/ctrl/l2tp/netlink.c index a50e9b2baaacb1055f026fe4ff69c63a07d56c46..0cc5b34b3ebb3eb1997ca1adb02021299b578ef0 100644 --- a/accel-pptpd/ctrl/l2tp/netlink.c +++ b/accel-pptpd/ctrl/l2tp/netlink.c @@ -5,13 +5,18 @@ #include "l2tp_kernel.h" #include "triton.h" -static struct nl_handle *nl_sock; static int family; void l2tp_nl_delete_tunnel(int tid) { - struct nl_msg *msg = nlmsg_alloc(); + struct nl_handle *nl_sock; + struct nl_msg *msg; + nl_sock = nl_handle_alloc(); + msg = nlmsg_alloc(); + + genl_connect(nl_sock); + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_REQUEST, L2TP_CMD_TUNNEL_DELETE, L2TP_GENL_VERSION); nla_put_u32(msg, L2TP_ATTR_CONN_ID, tid); @@ -19,15 +24,20 @@ void l2tp_nl_delete_tunnel(int tid) nl_recvmsgs_default(nl_sock); nlmsg_free(msg); - + nl_close(nl_sock); + nl_handle_destroy(nl_sock); } void l2tp_nl_create_tunnel(int fd, int tid, int peer_tid) { - struct nl_msg *msg = nlmsg_alloc(); - - l2tp_nl_delete_tunnel(tid); + struct nl_handle *nl_sock; + struct nl_msg *msg; + + nl_sock = nl_handle_alloc(); + msg = nlmsg_alloc(); + genl_connect(nl_sock); + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_REQUEST, L2TP_CMD_TUNNEL_CREATE, L2TP_GENL_VERSION); nla_put_u16(msg, L2TP_ATTR_ENCAP_TYPE, L2TP_ENCAPTYPE_UDP); nla_put_u8(msg, L2TP_ATTR_PROTO_VERSION, 2); @@ -40,12 +50,20 @@ void l2tp_nl_create_tunnel(int fd, int tid, int peer_tid) nl_recvmsgs_default(nl_sock); nlmsg_free(msg); + nl_close(nl_sock); + nl_handle_destroy(nl_sock); } void l2tp_nl_create_session(int tid, int sid, int peer_sid) { - struct nl_msg *msg = nlmsg_alloc(); + struct nl_handle *nl_sock; + struct nl_msg *msg; + + nl_sock = nl_handle_alloc(); + msg = nlmsg_alloc(); + genl_connect(nl_sock); + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_REQUEST, L2TP_CMD_SESSION_CREATE, L2TP_GENL_VERSION); nla_put_u32(msg, L2TP_ATTR_CONN_ID, tid); nla_put_u32(msg, L2TP_ATTR_SESSION_ID, sid); @@ -58,13 +76,19 @@ void l2tp_nl_create_session(int tid, int sid, int peer_sid) nl_recvmsgs_default(nl_sock); nlmsg_free(msg); + nl_close(nl_sock); + nl_handle_destroy(nl_sock); } static void __init init(void) { - nl_sock = nl_handle_alloc(); + struct nl_handle *nl_sock = nl_handle_alloc(); genl_connect(nl_sock); family = genl_ctrl_resolve(nl_sock, L2TP_GENL_NAME); + + nl_close(nl_sock); + nl_handle_destroy(nl_sock); } + diff --git a/accel-pptpd/ctrl/l2tp/packet.c b/accel-pptpd/ctrl/l2tp/packet.c index c127619b1b0a75c213aaa92460e0a0b0c09c3cc1..2f1b60fe8e7c173d827a5b1263c7b0716aa37dc4 100644 --- a/accel-pptpd/ctrl/l2tp/packet.c +++ b/accel-pptpd/ctrl/l2tp/packet.c @@ -107,6 +107,8 @@ int l2tp_recv(int fd, struct l2tp_packet_t **p) struct sockaddr_in addr; socklen_t len = sizeof(addr); + *p = NULL; + if (!buf) { log_emerg("l2tp: out of memory\n"); return 0; @@ -115,10 +117,9 @@ int l2tp_recv(int fd, struct l2tp_packet_t **p) n = recvfrom(fd, buf, L2TP_MAX_PACKET_SIZE, 0, &addr, &len); if (n < 0) { - if (errno == EAGAIN) { - mempool_free(buf); + mempool_free(buf); + if (errno == EAGAIN) return -1; - } log_error("l2tp: recv: %s\n", strerror(errno)); return 0; } diff --git a/accel-pptpd/extra/shaper_tbf.c b/accel-pptpd/extra/shaper_tbf.c index 07168d55c0b9723f4c94e6da8abdf4dc849aee94..7ed68f5e25cf79dc3dc134395a9223261572fdd7 100644 --- a/accel-pptpd/extra/shaper_tbf.c +++ b/accel-pptpd/extra/shaper_tbf.c @@ -21,10 +21,11 @@ #include "radius.h" #include "log.h" #include "ppp.h" +#include "memdebug.h" #define TIME_UNITS_PER_SEC 1000000 -//static int conf_verbose = 0; +static int conf_verbose = 0; static int conf_attr_down = 11; //Filter-Id static int conf_attr_up = 11; //Filter-Id static double conf_burst_factor = 0.1; @@ -34,6 +35,15 @@ static int conf_mpu = 0; static double tick_in_usec = 1; static double clock_factor = 1; +struct shaper_pd_t +{ + struct ppp_pd_t pd; + int down_speed; + int up_speed; +}; + +static void *pd_key; + static unsigned tc_time2tick(unsigned time) { return time*tick_in_usec; @@ -311,7 +321,7 @@ nla_put_failure: } -static void install_shaper(const char *ifname, int down_speed, int up_speed) +static int install_shaper(const char *ifname, int down_speed, int up_speed) { struct nl_handle *h; struct ifreq ifr; @@ -322,13 +332,13 @@ static void install_shaper(const char *ifname, int down_speed, int up_speed) if (ioctl(sock_fd, SIOCGIFINDEX, &ifr)) { log_ppp_error("tbf: ioctl(SIOCGIFINDEX)", strerror(errno)); - return; + return -1; } h = nl_handle_alloc(); if (!h) { log_ppp_error("tbf: nl_handle_alloc failed\n"); - return; + return -1; } err = nl_connect(h, NETLINK_ROUTE); @@ -338,19 +348,52 @@ static void install_shaper(const char *ifname, int down_speed, int up_speed) } if (down_speed) - install_tbf(h, ifr.ifr_ifindex, down_speed); + if (install_tbf(h, ifr.ifr_ifindex, down_speed)) + return -1; if (up_speed) { - install_ingress(h, ifr.ifr_ifindex); - install_filter(h, ifr.ifr_ifindex, up_speed); + if (install_ingress(h, ifr.ifr_ifindex)) + return -1; + if (install_filter(h, ifr.ifr_ifindex, up_speed)) + return -1; } nl_close(h); out: nl_handle_destroy(h); + + return 0; +} + +static struct shaper_pd_t *find_pd(struct ppp_t *ppp, int create) +{ + struct ppp_pd_t *pd; + struct shaper_pd_t *spd; + + list_for_each_entry(pd, &ppp->pd_list, entry) { + if (pd->key == &pd_key) { + spd = container_of(pd, typeof(*spd), pd); + return spd; + } + } + + if (create) { + spd = _malloc(sizeof(*spd)); + if (!spd) { + log_emerg("tbf: out of memory\n"); + return NULL; + } + + memset(spd, 0, sizeof(*spd)); + list_add_tail(&spd->pd.entry, &ppp->pd_list); + spd->pd.key = &pd_key; + return spd; + } + + return NULL; } -static void remove_shaper(const char *ifname) +static int remove_shaper(const char *ifname) { struct nl_handle *h; struct ifreq ifr; @@ -362,7 +405,7 @@ static void remove_shaper(const char *ifname) if (ioctl(sock_fd, SIOCGIFINDEX, &ifr)) { log_ppp_error("tbf: ioctl(SIOCGIFINDEX)", strerror(errno)); - return; + return -1; } struct tcmsg tchdr1 = { @@ -382,13 +425,14 @@ static void remove_shaper(const char *ifname) h = nl_handle_alloc(); if (!h) { log_ppp_error("tbf: nl_handle_alloc failed\n"); - return; + return -1; } err = nl_connect(h, NETLINK_ROUTE); if (err < 0) { log_ppp_error("tbf: nl_connect: %s", strerror(errno)); - goto out; + nl_handle_destroy(h); + return -1; } pmsg = nlmsg_alloc_simple(RTM_DELQDISC, NLM_F_CREATE | NLM_F_REPLACE); @@ -422,18 +466,20 @@ static void remove_shaper(const char *ifname) nlmsg_free(pmsg); nl_close(h); -out: nl_handle_destroy(h); - return; + return 0; out_err: log_ppp_error("tbf: failed to remove shaper\n"); - nlmsg_free(pmsg); + if (pmsg) + nlmsg_free(pmsg); + nl_close(h); nl_handle_destroy(h); -} + return -1; +} static int parse_attr(struct rad_attr_t *attr) { @@ -450,6 +496,10 @@ static void ev_radius_access_accept(struct ev_radius_t *ev) struct rad_attr_t *attr; int down_speed = 0; int up_speed = 0; + struct shaper_pd_t *pd = find_pd(ev->ppp, 1); + + if (!pd) + return; list_for_each_entry(attr, &ev->reply->attrs, entry) { if (attr->attr->id == conf_attr_down) @@ -458,8 +508,14 @@ static void ev_radius_access_accept(struct ev_radius_t *ev) up_speed = parse_attr(attr); } - if (down_speed > 0 && up_speed > 0) - install_shaper(ev->ppp->ifname, down_speed, up_speed); + if (down_speed > 0 && up_speed > 0) { + pd->down_speed = down_speed; + pd->up_speed = up_speed; + if (!install_shaper(ev->ppp->ifname, down_speed, up_speed)) { + if (conf_verbose) + log_ppp_info("tbf: installed shaper %i/%i (Kbit)\n", down_speed, up_speed); + } + } } static void ev_radius_coa(struct ev_radius_t *ev) @@ -467,6 +523,12 @@ static void ev_radius_coa(struct ev_radius_t *ev) struct rad_attr_t *attr; int down_speed = 0; int up_speed = 0; + struct shaper_pd_t *pd = find_pd(ev->ppp, 1); + + if (!pd) { + ev->res = -1; + return; + } list_for_each_entry(attr, &ev->request->attrs, entry) { if (attr->attr->id == conf_attr_down) @@ -475,10 +537,38 @@ static void ev_radius_coa(struct ev_radius_t *ev) up_speed = parse_attr(attr); } - remove_shaper(ev->ppp->ifname); + if (pd->down_speed != down_speed || pd->up_speed != up_speed) { + pd->down_speed = down_speed; + pd->up_speed = up_speed; + + if (remove_shaper(ev->ppp->ifname)) { + ev->res = -1; + return; + } + + if (down_speed > 0 || up_speed > 0) { + if (install_shaper(ev->ppp->ifname, down_speed, up_speed)) { + ev->res= -1; + return; + } else { + if (conf_verbose) + log_ppp_info("tbf: changed shaper %i/%i (Kbit)\n", down_speed, up_speed); + } + } else { + if (conf_verbose) + log_ppp_info("tbf: removed shaper\n"); + } + } +} - if (down_speed > 0 && up_speed > 0) - install_shaper(ev->ppp->ifname, down_speed, up_speed); +static void ev_ctrl_finished(struct ppp_t *ppp) +{ + struct shaper_pd_t *pd = find_pd(ppp, 0); + + if (pd) { + list_del(&pd->pd.entry); + _free(pd); + } } static int clock_init(void) @@ -560,6 +650,10 @@ static void __init init(void) if (opt && atoi(opt) >= 0) conf_mpu = atoi(opt); + opt = conf_get_opt("tbf", "verbose"); + if (opt && atoi(opt) > 0) + conf_verbose = 1; + if (conf_attr_up <= 0 || conf_attr_down <= 0) { log_emerg("tbf: incorrect attribute(s), tbf disabled...\n"); return; @@ -567,5 +661,6 @@ static void __init init(void) triton_event_register_handler(EV_RADIUS_ACCESS_ACCEPT, (triton_event_func)ev_radius_access_accept); triton_event_register_handler(EV_RADIUS_COA, (triton_event_func)ev_radius_coa); + triton_event_register_handler(EV_CTRL_FINISHED, (triton_event_func)ev_ctrl_finished); } diff --git a/accel-pptpd/radius/acct.c b/accel-pptpd/radius/acct.c index d855d120c764bcdd72611c8bbe60f7b93b655037..f6127029a12fa992faf29e52a2ed04cfbf04d329 100644 --- a/accel-pptpd/radius/acct.c +++ b/accel-pptpd/radius/acct.c @@ -64,19 +64,34 @@ static void req_set_stat(struct rad_req_t *req, struct ppp_t *ppp) static int rad_acct_read(struct triton_md_handler_t *h) { struct rad_req_t *req = container_of(h, typeof(*req), hnd); + struct rad_packet_t *pack; + int r; - if (req->reply) + if (req->reply) { rad_packet_free(req->reply); + req->reply = NULL; + } - req->reply = rad_packet_recv(h->fd, NULL); - if (!req->reply) - return 0; + while (1) { + r = rad_packet_recv(h->fd, &pack, NULL); + + if (pack) { + if (req->reply) + rad_packet_free(req->reply); + req->reply = pack; + if (conf_verbose) { + log_ppp_info("recv "); + rad_packet_print(req->reply, log_ppp_info); + } + } - if (conf_verbose) { - log_ppp_info("recv "); - rad_packet_print(req->reply, log_ppp_info); + if (r) + break; } + if (!req->reply) + return 0; + if (req->reply->code != CODE_ACCOUNTING_RESPONSE || req->reply->id != req->pack->id) { rad_packet_free(req->reply); req->reply = NULL; diff --git a/accel-pptpd/radius/dm_coa.c b/accel-pptpd/radius/dm_coa.c index 64fe97ac0c6c5833b35a2262aab31f4cd643e314..2fb023c0fc60fac657f9d7eaf73f692b1e5fb188 100644 --- a/accel-pptpd/radius/dm_coa.c +++ b/accel-pptpd/radius/dm_coa.c @@ -172,62 +172,64 @@ static int dm_coa_read(struct triton_md_handler_t *h) int err_code; struct sockaddr_in addr; + while (1) { + if (rad_packet_recv(h->fd, &pack, &addr)) + return 0; + + if (!pack) + continue; + + if (pack->code != CODE_DISCONNECT_REQUEST && pack->code != CODE_COA_REQUEST) { + log_warn("radius:dm_coa: unexpected code (%i) received\n", pack->code); + goto out_err_no_reply; + } + + if (dm_coa_check_RA(pack, conf_dm_coa_secret)) { + log_warn("radius:dm_coa: RA validation failed\n"); + goto out_err_no_reply; + } + + if (conf_verbose) { + log_debug("recv "); + rad_packet_print(pack, log_debug); + } + + if (rad_check_nas_pack(pack)) { + log_warn("radius:dm_coa: NAS identification failed\n"); + err_code = 403; + goto out_err; + } + + rpd = rad_find_session_pack(pack); + if (!rpd) { + log_warn("radius:dm_coa: session not found\n"); + err_code = 503; + goto out_err; + } + + if (rpd->dm_coa_req) { + pthread_mutex_unlock(&rpd->lock); + goto out_err_no_reply; + } + + rpd->dm_coa_req = pack; + memcpy(&rpd->dm_coa_addr, &addr, sizeof(addr)); + + if (pack->code == CODE_DISCONNECT_REQUEST) + triton_context_call(rpd->ppp->ctrl->ctx, (void (*)(void *))disconnect_request, rpd); + else + triton_context_call(rpd->ppp->ctrl->ctx, (void (*)(void *))coa_request, rpd); - pack = rad_packet_recv(h->fd, &addr); - if (!pack) - return 0; - - if (pack->code != CODE_DISCONNECT_REQUEST && pack->code != CODE_COA_REQUEST) { - log_warn("radius:dm_coa: unexpected code (%i) received\n", pack->code); - goto out_err_no_reply; - } - - if (dm_coa_check_RA(pack, conf_dm_coa_secret)) { - log_warn("radius:dm_coa: RA validation failed\n"); - goto out_err_no_reply; - } - - if (conf_verbose) { - log_debug("recv "); - rad_packet_print(pack, log_debug); - } - - if (rad_check_nas_pack(pack)) { - log_warn("radius:dm_coa: NAS identification failed\n"); - err_code = 403; - goto out_err; - } - - rpd = rad_find_session_pack(pack); - if (!rpd) { - log_warn("radius:dm_coa: session not found\n"); - err_code = 503; - goto out_err; - } - - if (rpd->dm_coa_req) { pthread_mutex_unlock(&rpd->lock); - goto out_err_no_reply; - } - - rpd->dm_coa_req = pack; - memcpy(&rpd->dm_coa_addr, &addr, sizeof(addr)); - - if (pack->code == CODE_DISCONNECT_REQUEST) - triton_context_call(rpd->ppp->ctrl->ctx, (void (*)(void *))disconnect_request, rpd); - else - triton_context_call(rpd->ppp->ctrl->ctx, (void (*)(void *))coa_request, rpd); - pthread_mutex_unlock(&rpd->lock); - - return 0; + continue; -out_err: - dm_coa_send_nak(h->fd, pack, &addr, err_code); + out_err: + dm_coa_send_nak(h->fd, pack, &addr, err_code); -out_err_no_reply: - rad_packet_free(pack); - return 0; + out_err_no_reply: + rad_packet_free(pack); + } } static void dm_coa_close(struct triton_context_t *ctx) diff --git a/accel-pptpd/radius/packet.c b/accel-pptpd/radius/packet.c index e3d4cfc0ec28d963347b9d21093a601ab7ddcf68..0277e5f37daa3b5cc1e200665869b52ff9c56ef3 100644 --- a/accel-pptpd/radius/packet.c +++ b/accel-pptpd/radius/packet.c @@ -97,7 +97,7 @@ int rad_packet_build(struct rad_packet_t *pack, uint8_t *RA) return 0; } -struct rad_packet_t *rad_packet_recv(int fd, struct sockaddr_in *addr) +int rad_packet_recv(int fd, struct rad_packet_t **p, struct sockaddr_in *addr) { struct rad_packet_t *pack; struct rad_attr_t *attr; @@ -107,9 +107,11 @@ struct rad_packet_t *rad_packet_recv(int fd, struct sockaddr_in *addr) int n, id, len, vendor_id; socklen_t addr_len = sizeof(*addr); + *p = NULL; + pack = rad_packet_alloc(0); if (!pack) - return NULL; + return 0; pack->buf = _malloc(REQ_LENGTH_MAX); if (!pack->buf) { @@ -123,8 +125,9 @@ struct rad_packet_t *rad_packet_recv(int fd, struct sockaddr_in *addr) else n = read(fd, pack->buf, REQ_LENGTH_MAX); if (n < 0) { - if (errno == EINTR) - continue; + rad_packet_free(pack); + if (errno == EAGAIN) + return -1; log_ppp_error("radius:packet:read: %s\n", strerror(errno)); goto out_err; } @@ -219,11 +222,13 @@ struct rad_packet_t *rad_packet_recv(int fd, struct sockaddr_in *addr) n -= 2 + len; } - return pack; + *p = pack; + + return 0; out_err: rad_packet_free(pack); - return NULL; + return 0; } void rad_packet_free(struct rad_packet_t *pack) diff --git a/accel-pptpd/radius/radius_p.h b/accel-pptpd/radius/radius_p.h index 9537641bddcc80393272b7ed39868308d859ee86..e7b6216fffa9e8ce5e9e703a87dcf7b9f829ba18 100644 --- a/accel-pptpd/radius/radius_p.h +++ b/accel-pptpd/radius/radius_p.h @@ -86,7 +86,7 @@ void rad_acct_stop(struct radius_pd_t *rpd); struct rad_packet_t *rad_packet_alloc(int code); int rad_packet_build(struct rad_packet_t *pack, uint8_t *RA); -struct rad_packet_t *rad_packet_recv(int fd, struct sockaddr_in *addr); +int rad_packet_recv(int fd, struct rad_packet_t **, struct sockaddr_in *addr); void rad_packet_free(struct rad_packet_t *); void rad_packet_print(struct rad_packet_t *pack, void (*print)(const char *fmt, ...)); int rad_packet_send(struct rad_packet_t *pck, int fd, struct sockaddr_in *addr); diff --git a/accel-pptpd/radius/req.c b/accel-pptpd/radius/req.c index f3f41386f21ab62e16cb71b1dfdaa8f21cd3a248..5b1261fee758980344763b8aebff866828739ec1 100644 --- a/accel-pptpd/radius/req.c +++ b/accel-pptpd/radius/req.c @@ -196,8 +196,22 @@ static void req_wakeup(struct rad_req_t *req) static int rad_req_read(struct triton_md_handler_t *h) { struct rad_req_t *req = container_of(h, typeof(*req), hnd); + struct rad_packet_t *pack; + int r; + + while (1) { + r = rad_packet_recv(h->fd, &pack, NULL); + + if (pack) { + if (req->reply) + rad_packet_free(req->reply); + req->reply = pack; + } + + if (r) + break; + } - req->reply = rad_packet_recv(h->fd, NULL); req_wakeup(req); return 0; diff --git a/accel-pptpd/triton/mempool.c b/accel-pptpd/triton/mempool.c index c96c3ba241f7aadbdd3eeb82c5427432c57333b4..bd951b43d08ff4b393d2069a176461952ffa8bea 100644 --- a/accel-pptpd/triton/mempool.c +++ b/accel-pptpd/triton/mempool.c @@ -14,6 +14,9 @@ struct _mempool_t struct list_head entry; int size; struct list_head items; +#ifdef MEMDEBUG + struct list_head ditems; +#endif spinlock_t lock; uint64_t magic; }; @@ -22,6 +25,10 @@ struct _item_t { struct _mempool_t *owner; struct list_head entry; +#ifdef MEMDEBUG + const char *fname; + int line; +#endif uint64_t magic2; uint64_t magic1; char ptr[0]; @@ -30,12 +37,15 @@ struct _item_t static LIST_HEAD(pools); static spinlock_t pools_lock = SPINLOCK_INITIALIZER; -__export mempool_t *mempool_create(int size) +mempool_t __export *mempool_create(int size) { struct _mempool_t *p = _malloc(sizeof(*p)); memset(p, 0, sizeof(*p)); INIT_LIST_HEAD(&p->items); +#ifdef MEMDEBUG + INIT_LIST_HEAD(&p->ditems); +#endif spinlock_init(&p->lock); p->size = size; p->magic = (uint64_t)random() * (uint64_t)random(); @@ -48,7 +58,7 @@ __export mempool_t *mempool_create(int size) } #ifndef MEMDEBUG -__export void *mempool_alloc(mempool_t *pool) +void __export *mempool_alloc(mempool_t *pool) { struct _mempool_t *p = (struct _mempool_t *)pool; struct _item_t *it; @@ -94,7 +104,11 @@ void __export *mempool_alloc_md(mempool_t *pool, const char *fname, int line) if (!list_empty(&p->items)) { it = list_entry(p->items.next, typeof(*it), entry); list_del(&it->entry); + list_add(&it->entry, &p->ditems); spin_unlock(&p->lock); + + it->fname = fname; + it->line = line; __sync_fetch_and_sub(&triton_stat.mempool_available, size); @@ -112,19 +126,26 @@ void __export *mempool_alloc_md(mempool_t *pool, const char *fname, int line) it->owner = p; it->magic2 = p->magic; it->magic1 = MAGIC1; + it->fname = fname; + it->line = line; *(uint64_t*)(it->ptr + p->size) = it->magic2; + spin_lock(&p->lock); + list_add(&it->entry, &p->ditems); + spin_unlock(&p->lock); + __sync_fetch_and_add(&triton_stat.mempool_allocated, size); return it->ptr; } -__export void mempool_free(void *ptr) +void __export mempool_free(void *ptr) { struct _item_t *it = container_of(ptr, typeof(*it), ptr); uint32_t size = sizeof(*it) + it->owner->size + 8; +#ifdef MEMDEBUG if (it->magic1 != MAGIC1) { triton_log_error("mempool: memory corruption detected"); abort(); @@ -141,14 +162,48 @@ __export void mempool_free(void *ptr) } it->magic1 = 0; +#endif spin_lock(&it->owner->lock); +#ifdef MEMDEBUG + list_del(&it->entry); +#endif list_add_tail(&it->entry,&it->owner->items); spin_unlock(&it->owner->lock); __sync_fetch_and_add(&triton_stat.mempool_available, size); } +void __export mempool_clean(mempool_t *pool) +{ + struct _mempool_t *p = (struct _mempool_t *)pool; + struct _item_t *it; + uint32_t size = sizeof(*it) + p->size + 8; + + spin_lock(&p->lock); + while (!list_empty(&p->items)) { + it = list_entry(p->items.next, typeof(*it), entry); + list_del(&it->entry); + _free(it); + __sync_fetch_and_sub(&triton_stat.mempool_allocated, size); + __sync_fetch_and_sub(&triton_stat.mempool_available, size); + } + spin_unlock(&p->lock); +} + +#ifdef MEMDEBUG +void __export mempool_show(mempool_t *pool) +{ + struct _mempool_t *p = (struct _mempool_t *)pool; + struct _item_t *it; + + spin_lock(&p->lock); + list_for_each_entry(it, &p->ditems, entry) + triton_log_error("%s:%i %p\n", it->fname, it->line, it->ptr); + spin_unlock(&p->lock); +} +#endif + void sigclean(int num) { struct _mempool_t *p; @@ -159,7 +214,7 @@ void sigclean(int num) spin_lock(&pools_lock); list_for_each_entry(p, &pools, entry) { - size = sizeof(*it) + p->size; + size = sizeof(*it) + p->size + 8; spin_lock(&p->lock); while (!list_empty(&p->items)) { it = list_entry(p->items.next, typeof(*it), entry); @@ -177,3 +232,4 @@ static void __init init(void) { signal(35, sigclean); } +