From 77b5bdd209312d58afd3926bdf45c3fd124ef0ed Mon Sep 17 00:00:00 2001 From: Michael Blizek Date: Wed, 8 Jun 2011 19:32:57 +0200 Subject: [PATCH] embed data_buf_item in skb->cb, bogus neighbor_free fixed, connect_neigh: control_msg oom handling fixed --- net/cor/common.c | 21 ++++--- net/cor/cor.h | 14 ++--- net/cor/forward.c | 161 ++++++++++++++++-------------------------------------- net/cor/rcv.c | 12 +++- 4 files changed, 74 insertions(+), 134 deletions(-) diff --git a/net/cor/common.c b/net/cor/common.c index e2675a07a66..aa5b2d92099 100644 --- a/net/cor/common.c +++ b/net/cor/common.c @@ -1075,7 +1075,7 @@ out: * rc == 2 addrtype not found * rc == 3 addr not found * rc == 4 ==> connid allocation failed - * rc == 5 ==> control msg alloc failed + * rc == 4 ==> control msg alloc failed */ int connect_neigh(struct conn *trtg_unconn_l, __u16 addrtypelen, __u8 *addrtype, @@ -1089,24 +1089,29 @@ int connect_neigh(struct conn *trtg_unconn_l, if (nb == 0) return 3; + cm = alloc_control_msg(nb, ACM_PRIORITY_HIGH); + if (unlikely(cm == 0)) { + rc = 4; + goto neigh_kref; + } + mutex_lock(&(trtg_unconn_l->reversedir->rcv_lock)); ciorc = conn_init_out(trtg_unconn_l, nb); mutex_unlock(&(trtg_unconn_l->reversedir->rcv_lock)); if (unlikely(ciorc)) { rc = 4; - goto neigh_kref; - } - - cm = alloc_control_msg(nb, ACM_PRIORITY_HIGH); - if (unlikely(cm == 0)) { - rc = 5; - goto neigh_kref; + goto freecm; } send_connect_nb(cm, trtg_unconn_l->reversedir->source.in.conn_id, trtg_unconn_l->reversedir->source.in.next_seqno, trtg_unconn_l->reversedir); + if (0) { +freecm: + free_control_msg(cm); + } + neigh_kref: kref_put(&(nb->ref), neighbor_free); diff --git a/net/cor/cor.h b/net/cor/cor.h index e045f245cab..a448e74ba70 100644 --- a/net/cor/cor.h +++ b/net/cor/cor.h @@ -492,16 +492,9 @@ struct cor_sched_data{ struct data_buf_item{ struct list_head buf_list; - union { - struct { - char *buf; - __u16 datalen; - __u16 buflen; - - }buf; - - struct sk_buff *skb; - }data; + char *buf; + __u16 datalen; + __u16 buflen; __u8 type; }; @@ -785,6 +778,7 @@ struct skb_procstate{ struct{ __u32 seqno; + struct data_buf_item dbi; }rcv2; }funcstate; }; diff --git a/net/cor/forward.c b/net/cor/forward.c index d9afff19f93..e6ca20155c9 100644 --- a/net/cor/forward.c +++ b/net/cor/forward.c @@ -34,22 +34,20 @@ void databuf_init(struct conn *cn_init) static void databuf_item_free(struct conn *cn_l, struct data_buf_item *item) { + list_del(&(item->buf_list)); if (item->type == TYPE_BUF) { - kfree(item->data.buf.buf); - cn_l->data_buf.overhead -= item->data.buf.buflen - - item->data.buf.datalen; + cn_l->data_buf.overhead -= sizeof(struct data_buf_item) + + item->buflen - item->datalen; + kfree(item->buf); + kmem_cache_free(data_buf_item_slab, item); } else if (item->type == TYPE_SKB) { - kfree_skb(item->data.skb); + struct sk_buff *skb = skb_from_pstate(container_of(item, + struct skb_procstate, funcstate.rcv2.dbi)); cn_l->data_buf.overhead -= sizeof(struct sk_buff); + kfree_skb(skb); } else { BUG(); } - - cn_l->data_buf.overhead -= sizeof(struct data_buf_item); - - list_del(&(item->buf_list)); - - kmem_cache_free(data_buf_item_slab, item); } void databuf_free(struct conn *cn_l) @@ -58,13 +56,7 @@ void databuf_free(struct conn *cn_l) struct data_buf_item *item = container_of( cn_l->data_buf.items.next, struct data_buf_item, buf_list); - if (item->type == TYPE_BUF) { - cn_l->data_buf.totalsize -= item->data.buf.datalen; - } else if (item->type == TYPE_SKB) { - cn_l->data_buf.totalsize -= item->data.skb->len; - } else { - BUG(); - } + cn_l->data_buf.totalsize -= item->datalen; databuf_item_free(cn_l, item); } @@ -90,7 +82,8 @@ static void databuf_nextreadchunk(struct conn *cn_l) if (cn_l->data_buf.lastread == 0) { BUG_ON(cn_l->data_buf.last_read_offset != 0); BUG_ON(list_empty(&(cn_l->data_buf.items))); - cn_l->data_buf.lastread = container_of(cn_l->data_buf.items.next, + cn_l->data_buf.lastread = container_of( + cn_l->data_buf.items.next, struct data_buf_item, buf_list); } else if (&(cn_l->data_buf.lastread->buf_list) != cn_l->data_buf.items.prev) { @@ -115,26 +108,15 @@ static int _databuf_pull(struct conn *cn_l, char *dst, int len, int userbuf) int rc = 0; int cpy = len; - char *srcbuf = 0; - int srcbuflen = 0; - char *srcbufcpystart = 0; int srcbufcpylen = 0; BUG_ON(cn_l->data_buf.lastread == 0); - if (cn_l->data_buf.lastread->type == TYPE_BUF) { - srcbuf = cn_l->data_buf.lastread->data.buf.buf; - srcbuflen = cn_l->data_buf.lastread->data.buf.datalen; - } else if (cn_l->data_buf.lastread->type == TYPE_SKB) { - srcbuf = cn_l->data_buf.lastread->data.skb->data; - srcbuflen = cn_l->data_buf.lastread->data.skb->len; - } else { - BUG(); - } - - srcbufcpystart = srcbuf + cn_l->data_buf.last_read_offset; - srcbufcpylen = srcbuflen - cn_l->data_buf.last_read_offset; + srcbufcpystart = cn_l->data_buf.lastread->buf + + cn_l->data_buf.last_read_offset; + srcbufcpylen = cn_l->data_buf.lastread->datalen - + cn_l->data_buf.last_read_offset; if (cpy > srcbufcpylen) cpy = srcbufcpylen; @@ -246,22 +228,12 @@ void databuf_pullold(struct conn *trgt_out_l, __u32 startpos, char *dst, struct data_buf_item, buf_list); while(1) { - int srcbuflen; - BUG_ON(&(dbi->buf_list) == &(trgt_out_l->data_buf.items)); - if (dbi->type == TYPE_BUF) { - srcbuflen = dbi->data.buf.datalen; - } else if (dbi->type == TYPE_SKB) { - srcbuflen = dbi->data.skb->len; - } else { - BUG(); - } - - if (((__s32) (pos + srcbuflen - startpos)) > 0) + if (((__s32) (pos + dbi->datalen - startpos)) > 0) break; - pos += srcbuflen; + pos += dbi->datalen; dbi = container_of(dbi->buf_list.next, struct data_buf_item, buf_list); } @@ -269,28 +241,15 @@ void databuf_pullold(struct conn *trgt_out_l, __u32 startpos, char *dst, while (len > 0) { int cpy = len; - char *srcbuf = 0; - int srcbuflen = 0; - char *srcbufcpystart = 0; int srcbufcpylen = 0; BUG_ON(&(dbi->buf_list) == &(trgt_out_l->data_buf.items)); - if (dbi->type == TYPE_BUF) { - srcbuf = dbi->data.buf.buf; - srcbuflen = dbi->data.buf.datalen; - } else if (dbi->type == TYPE_SKB) { - srcbuf = dbi->data.skb->data; - srcbuflen = dbi->data.skb->len; - } else { - BUG(); - } - BUG_ON(((__s32) (pos - startpos)) > 0); - srcbufcpystart = srcbuf + ((__s32) (startpos - pos)); - srcbufcpylen = srcbuflen - ((__s32) (startpos - pos)); + srcbufcpystart = dbi->buf + ((__s32) (startpos - pos)); + srcbufcpylen = dbi->datalen - ((__s32) (startpos - pos)); if (cpy > srcbufcpylen) cpy = srcbufcpylen; @@ -301,7 +260,7 @@ void databuf_pullold(struct conn *trgt_out_l, __u32 startpos, char *dst, len -= cpy; startpos += cpy; - pos += srcbuflen; + pos += dbi->datalen; dbi = container_of(dbi->buf_list.next, struct data_buf_item, buf_list); } @@ -316,25 +275,16 @@ void databuf_ack(struct conn *trgt_out_l, __u32 pos) struct data_buf_item *firstitem = container_of( trgt_out_l->data_buf.items.next, struct data_buf_item, buf_list); - int firstlen = 0; if (firstitem == trgt_out_l->data_buf.lastread) break; - if (firstitem->type == TYPE_BUF) { - firstlen = firstitem->data.buf.datalen; - } else if (firstitem->type == TYPE_SKB) { - firstlen = firstitem->data.skb->len; - } else { - BUG(); - } - - if ( ((__s32) (trgt_out_l->data_buf.first_offset + firstlen - - pos)) > 0) + if ( ((__s32) (trgt_out_l->data_buf.first_offset + + firstitem->datalen - pos)) > 0) break; - trgt_out_l->data_buf.first_offset += firstlen; - acked += firstlen; + trgt_out_l->data_buf.first_offset += firstitem->datalen; + acked += firstitem->datalen; databuf_item_free(trgt_out_l, firstitem); } @@ -368,13 +318,7 @@ void databuf_ackread(struct conn *cn_l) if (firstitem == cn_l->data_buf.lastread) break; - if (firstitem->type == TYPE_BUF) { - acked += firstitem->data.buf.datalen; - } else if (firstitem->type == TYPE_SKB) { - acked += firstitem->data.skb->len; - } else { - BUG(); - } + acked += firstitem->datalen; databuf_item_free(cn_l, firstitem); } @@ -411,9 +355,7 @@ static __s64 _receive_buf(struct conn *cn_l, char *buf, __u32 len, int userbuf, int rc = 0; int cpy = len; - if (item == 0 || item->type != TYPE_BUF || - item->data.buf.buflen <= - item->data.buf.datalen) { + if (item == 0 || item->buflen <= item->datalen) { __u32 buflen = len; if (maxusage != 0) { @@ -459,37 +401,36 @@ static __s64 _receive_buf(struct conn *cn_l, char *buf, __u32 len, int userbuf, } memset(item, 0, sizeof(item)); item->type = TYPE_BUF; - item->data.buf.buf = kmalloc(buflen, GFP_KERNEL); + item->buf = kmalloc(buflen, GFP_KERNEL); - if (unlikely(item->data.buf.buf == 0)) { + if (unlikely(item->buf == 0)) { kmem_cache_free(data_buf_item_slab, item); rc = -ENOMEM; goto error; } - item->data.buf.datalen = 0; + item->datalen = 0; list_add_tail(&(item->buf_list), &(cn_l->data_buf.items)); - item->data.buf.buflen = buflen; + item->buflen = buflen; cn_l->data_buf.overhead += buflen + sizeof(struct data_buf_item); } BUG_ON(item->type != TYPE_BUF); - BUG_ON(item->data.buf.buflen <= item->data.buf.datalen); + BUG_ON(item->buflen <= item->datalen); - if (item->data.buf.buflen - item->data.buf.datalen < cpy) - cpy = (item->data.buf.buflen - item->data.buf.datalen); + if (item->buflen - item->datalen < cpy) + cpy = (item->buflen - item->datalen); if (userbuf) { - int notcopied = copy_from_user(item->data.buf.buf + - item->data.buf.datalen, buf, cpy); + int notcopied = copy_from_user(item->buf + + item->datalen, buf, cpy); cpy -= notcopied; if (unlikely(notcopied > 0)) rc = -EFAULT; } else { - memcpy(item->data.buf.buf + item->data.buf.datalen, - buf, cpy); + memcpy(item->buf + item->datalen, buf, cpy); } buf += cpy; @@ -501,7 +442,7 @@ static __s64 _receive_buf(struct conn *cn_l, char *buf, __u32 len, int userbuf, cn_l->data_buf.overhead != 0); totalcpy += cpy; - item->data.buf.datalen += cpy; + item->datalen += cpy; error: if (unlikely(rc < 0)) { @@ -566,29 +507,23 @@ void receive_cpacketresp(struct conn *trtg_unconn_l, char *buf, int len) int receive_skb(struct conn *src_in_l, struct sk_buff *skb) { - struct data_buf_item *item; + struct skb_procstate *ps = skb_pstate(skb); + struct data_buf_item *item = &(ps->funcstate.rcv2.dbi); - item = kmem_cache_alloc(data_buf_item_slab, GFP_KERNEL); - - if (unlikely(item == 0)) + if (unlikely(unlikely(src_in_l->data_buf.totalsize + skb->len > + (1 << 30)) || unlikely(src_in_l->data_buf.overhead > + (1 << 30)))) return 1; - item->data.skb = skb; item->type = TYPE_SKB; + item->buf = skb->data; + item->datalen = skb->len; + item->buflen = item->datalen; list_add_tail(&(item->buf_list), &(src_in_l->data_buf.items)); - if (unlikely(unlikely(src_in_l->data_buf.totalsize + skb->len > - (1 << 30)) || unlikely(src_in_l->data_buf.overhead > - (1 << 30)))) { - kmem_cache_free(data_buf_item_slab, item); - return 1; - } - src_in_l->data_buf.read_remaining += skb->len; - src_in_l->data_buf.totalsize += skb->len; - src_in_l->data_buf.overhead += sizeof(struct data_buf_item) + - sizeof(struct sk_buff); - BUG_ON(src_in_l->data_buf.totalsize == 0 && - src_in_l->data_buf.overhead != 0); + src_in_l->data_buf.read_remaining += item->datalen; + src_in_l->data_buf.totalsize += item->datalen; + src_in_l->data_buf.overhead += sizeof(struct sk_buff); return 0; } diff --git a/net/cor/rcv.c b/net/cor/rcv.c index 6a774e68477..317f5854298 100644 --- a/net/cor/rcv.c +++ b/net/cor/rcv.c @@ -682,7 +682,6 @@ void drain_ooo_queue(struct conn *src_in_l) if (src_in_l->source.in.next_seqno != ps->funcstate.rcv2.seqno) break; - #warning todo cont after drop == 1 drop = receive_skb(src_in_l, skb); if (drop) break; @@ -821,21 +820,28 @@ static void conn_rcv(struct neighbor *nb, struct sk_buff *skb, __u32 conn_id, struct conn *cn_src_in; struct skb_procstate *ps = skb_pstate(skb); + memset(ps, 0, sizeof(struct skb_procstate)); + ps->funcstate.rcv2.seqno = seqno; cn_src_in = get_conn(conn_id); if (unlikely(cn_src_in == 0)) { + int nbput = 0; printk(KERN_DEBUG "unknown conn_id when receiving: %d", conn_id); - if (nb == 0) + if (nb == 0) { nb = get_neigh_by_mac(skb); + nbput = 1; + } kfree_skb(skb); if (likely(nb != 0)) { send_connid_unknown(nb, conn_id); - kref_put(&(nb->ref), neighbor_free); + if (nbput) { + kref_put(&(nb->ref), neighbor_free); + } } return; } -- 2.11.4.GIT