From 0d202675764e25f77e15ecf3339ede5c52191602 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:09:21 -0500 Subject: [PATCH] Import 0.99.14z --- Makefile | 2 +- drivers/char/pty.c | 8 +++-- drivers/net/3c501.c | 6 ++-- drivers/net/3c507.c | 8 ++--- drivers/net/3c509.c | 8 ++--- drivers/net/8390.c | 10 +++--- drivers/net/at1700.c | 10 +++--- drivers/net/atp.c | 10 +++--- drivers/net/d_link.c | 8 ++--- drivers/net/eexpress.c | 6 ++-- drivers/net/lance.c | 12 +++---- drivers/net/plip.c | 8 ++--- drivers/net/skeleton.c | 10 +++--- drivers/net/slip.c | 12 ++++--- kernel/sched.c | 4 +-- net/inet/arp.c | 46 +++++++++++++++------------ net/inet/sock.c | 8 ++--- net/inet/sock.h | 3 +- net/inet/tcp.c | 72 ++++++++++++++++++++++++------------------ net/inet/tcp.h | 3 ++ 20 files changed, 141 insertions(+), 113 deletions(-) diff --git a/Makefile b/Makefile index 287c8170efa1..546d9765ef3e 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 0.99 PATCHLEVEL = 14 -ALPHA = y +ALPHA = z all: Version zImage diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 4797597d35c5..482afe6b2132 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -55,12 +55,14 @@ static inline void pty_copy(struct tty_struct * from, struct tty_struct * to) { unsigned long count, n; struct tty_queue *fq, *tq; + int skip_readq; if (from->stopped || EMPTY(&from->write_q)) return; fq = &from->write_q; /* Bypass the read_q if this is a pty master. */ - tq = IS_A_PTY_MASTER(to->line) ? &to->secondary : &to->read_q; + skip_readq = IS_A_PTY_MASTER(to->line) && to->disc == N_TTY; + tq = skip_readq ? &to->secondary : &to->read_q; count = MIN(CHARS(fq), LEFT(tq)); while (count) { n = MIN(MIN(TTY_BUF_SIZE - fq->tail, TTY_BUF_SIZE - tq->head), @@ -70,8 +72,8 @@ static inline void pty_copy(struct tty_struct * from, struct tty_struct * to) fq->tail = (fq->tail + n) & (TTY_BUF_SIZE - 1); tq->head = (tq->head + n) & (TTY_BUF_SIZE - 1); } - if (IS_A_PTY_MASTER(to->line)) - wake_up_interruptible(&tq->proc_list); + if (skip_readq) + wake_up_interruptible(&to->secondary.proc_list); else TTY_READ_FLUSH(to); if (LEFT(fq) > WAKEUP_CHARS) diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c index 9b9d4dbfc6ff..d0141b0e5f28 100644 --- a/drivers/net/3c501.c +++ b/drivers/net/3c501.c @@ -292,7 +292,7 @@ el_start_xmit(struct sk_buff *skb, struct device *dev) } /* Fill in the ethernet header. */ - if (!skb->arp && dev->rebuild_header(skb+1, dev)) { + if (!skb->arp && dev->rebuild_header(skb->data, dev)) { skb->dev = dev; arp_queue (skb); return 0; @@ -310,7 +310,7 @@ el_start_xmit(struct sk_buff *skb, struct device *dev) printk("%s: Transmitter access conflict.\n", dev->name); else { int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN); - unsigned char *buf = (void *)(skb+1); + unsigned char *buf = skb->data; el_status.tx_pkt_start = gp_start; el_status.collisions = 0; @@ -463,7 +463,7 @@ el_receive(struct device *dev) skb->len = pkt_len; skb->dev = dev; - insb(DATAPORT, (void *)(skb+1), pkt_len); + insb(DATAPORT, skb->data, pkt_len); #ifdef HAVE_NETIF_RX netif_rx(skb); diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c index f55131ff7534..ba53e06cc47d 100644 --- a/drivers/net/3c507.c +++ b/drivers/net/3c507.c @@ -484,7 +484,7 @@ el16_send_packet(struct sk_buff *skb, struct device *dev) /* For ethernet, fill in the header. This should really be done by a higher level, rather than duplicated for each ethernet adaptor. */ - if (!skb->arp && dev->rebuild_header(skb+1, dev)) { + if (!skb->arp && dev->rebuild_header(skb->data, dev)) { skb->dev = dev; arp_queue (skb); return 0; @@ -496,7 +496,7 @@ el16_send_packet(struct sk_buff *skb, struct device *dev) printk("%s: Transmitter access conflict.\n", dev->name); else { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = (void *)(skb+1); + unsigned char *buf = skb->data; /* Disable the 82586's input to the interrupt line. */ outb(0x80, ioaddr + MISC_CTRL); @@ -855,8 +855,8 @@ el16_rx(struct device *dev) skb->len = pkt_len; skb->dev = dev; - /* 'skb+1' points to the start of sk_buff data area. */ - memcpy((unsigned char *) (skb + 1), data_frame + 5, pkt_len); + /* 'skb->data' points to the start of sk_buff data area. */ + memcpy(skb->data, data_frame + 5, pkt_len); #ifdef HAVE_NETIF_RX netif_rx(skb); diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 0240a1bc562d..7e18ce77913a 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -366,7 +366,7 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev) } /* Fill in the ethernet header. */ - if (!skb->arp && dev->rebuild_header(skb+1, dev)) { + if (!skb->arp && dev->rebuild_header(skb->data, dev)) { skb->dev = dev; arp_queue (skb); return 0; @@ -404,7 +404,7 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev) outw(skb->len, ioaddr + TX_FIFO); outw(0x00, ioaddr + TX_FIFO); /* ... and the packet rounded to a doubleword. */ - outsl(ioaddr + TX_FIFO, (void *)(skb+1), (skb->len + 3) >> 2); + outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); dev->trans_start = jiffies; if (inw(ioaddr + TX_FREE) > 1536) { @@ -576,8 +576,8 @@ el3_rx(struct device *dev) skb->len = pkt_len; skb->dev = dev; - /* 'skb+1' points to the start of sk_buff data area. */ - insl(ioaddr+RX_FIFO, (void *)(skb+1), + /* 'skb->data' points to the start of sk_buff data area. */ + insl(ioaddr+RX_FIFO, skb->data, (pkt_len + 3) >> 2); #ifdef HAVE_NETIF_RX diff --git a/drivers/net/8390.c b/drivers/net/8390.c index e6759eafec1d..9c896cc59941 100644 --- a/drivers/net/8390.c +++ b/drivers/net/8390.c @@ -160,7 +160,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev) return 0; } /* Fill in the ethernet header. */ - if (!skb->arp && dev->rebuild_header(skb+1, dev)) { + if (!skb->arp && dev->rebuild_header(skb->data, dev)) { skb->dev = dev; arp_queue (skb); return 0; @@ -219,7 +219,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev) return 1; } dev->trans_start = jiffies; - ei_block_output(dev, length, (unsigned char *)(skb+1), output_page); + ei_block_output(dev, length, skb->data, output_page); if (! ei_local->txing) { NS8390_trigger_send(dev, send_length, output_page); if (output_page == ei_local->tx_start_page) @@ -233,7 +233,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev) tmp_tbusy = 1; } else { dev->trans_start = jiffies; - ei_block_output(dev, length, (unsigned char *)(skb+1), + ei_block_output(dev, length, skb->data, ei_local->tx_start_page); NS8390_trigger_send(dev, send_length, ei_local->tx_start_page); tmp_tbusy = 1; @@ -495,8 +495,8 @@ static void ei_receive(struct device *dev) skb->len = pkt_len; skb->dev = dev; - /* 'skb+1' points to the start of sk_buff data area. */ - ei_block_input(dev, pkt_len, (char *)(skb+1), + /* 'skb->data' points to the start of sk_buff data area. */ + ei_block_input(dev, pkt_len, (char *) skb->data, current_offset + sizeof(rx_frame)); #ifdef HAVE_NETIF_RX netif_rx(skb); diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c index d31cd66e3868..cfc5922d7d04 100644 --- a/drivers/net/at1700.c +++ b/drivers/net/at1700.c @@ -402,7 +402,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev) /* For ethernet, fill in the header. This should really be done by a higher level, rather than duplicated for each ethernet adaptor. */ - if (!skb->arp && dev->rebuild_header(skb+1, dev)) { + if (!skb->arp && dev->rebuild_header(skb->data, dev)) { skb->dev = dev; arp_queue (skb); return 0; @@ -415,7 +415,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev) printk("%s: Transmitter access conflict.\n", dev->name); else { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = (void *)(skb+1); + unsigned char *buf = skb->data; if (net_debug > 4) printk("%s: Transmitting a packet of length %d.\n", dev->name, @@ -551,14 +551,14 @@ net_rx(struct device *dev) skb->len = pkt_len; skb->dev = dev; - /* 'skb+1' points to the start of sk_buff data area. */ - insw(ioaddr + DATAPORT, (void *)(skb+1), (pkt_len + 1) >> 1); + /* 'skb->data' points to the start of sk_buff data area. */ + insw(ioaddr + DATAPORT, skb->data, (pkt_len + 1) >> 1); if (net_debug > 5) { int i; printk("%s: Rxed packet of length %d: ", dev->name, pkt_len); for (i = 0; i < 14; i++) - printk(" %02x", ((unsigned char*)(skb + 1))[i]); + printk(" %02x", skb->data[i]); printk(".\n"); } diff --git a/drivers/net/atp.c b/drivers/net/atp.c index e99d0249ee81..d86dc82235af 100644 --- a/drivers/net/atp.c +++ b/drivers/net/atp.c @@ -477,7 +477,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev) /* For ethernet, fill in the header. This should really be done by a higher level, rather than duplicated for each ethernet adaptor. */ - if (!skb->arp && dev->rebuild_header(skb+1, dev)) { + if (!skb->arp && dev->rebuild_header(skb->data, dev)) { skb->dev = dev; arp_queue (skb); return 0; @@ -490,7 +490,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev) printk("%s: Transmitter access conflict.\n", dev->name); else { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = (void *)(skb+1); + unsigned char *buf = skb->data; int flags; /* Disable interrupts by writing 0x00 to the Interrupt Mask Register. @@ -686,11 +686,11 @@ static void net_rx(struct device *dev) skb->len = pkt_len; skb->dev = dev; - /* 'skb+1' points to the start of sk_buff data area. */ - read_block(ioaddr, pkt_len, (unsigned char *)(skb + 1), dev->if_port); + /* 'skb->data' points to the start of sk_buff data area. */ + read_block(ioaddr, pkt_len, skb->data, dev->if_port); if (net_debug > 6) { - unsigned char *data = (unsigned char *)(skb + 1); + unsigned char *data = skb->data; printk(" data %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x..", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], diff --git a/drivers/net/d_link.c b/drivers/net/d_link.c index a8e79723a581..2ff8a1b1e920 100644 --- a/drivers/net/d_link.c +++ b/drivers/net/d_link.c @@ -386,7 +386,7 @@ d_link_start_xmit(struct sk_buff *skb, struct device *dev) int transmit_from; int len; int tickssofar; - unsigned char *buffer = (unsigned char *)(skb + 1); + unsigned char *buffer = skb->data; /* * If some higher layer thinks we've missed a @@ -401,7 +401,7 @@ d_link_start_xmit(struct sk_buff *skb, struct device *dev) /* For ethernet, fill in the header (hardware addresses) with an arp. */ if (!skb->arp) - if(dev->rebuild_header(skb + 1, dev)) { + if(dev->rebuild_header(skb->data, dev)) { skb->dev = dev; arp_queue (skb); return 0; @@ -590,8 +590,8 @@ d_link_rx_intr(struct device *dev) skb->lock = 0; skb->mem_len = sksize; skb->mem_addr = skb; - /* 'skb + 1' points to the start of sk_buff data area. */ - buffer = (unsigned char *)(skb + 1); + /* 'skb->data' points to the start of sk_buff data area. */ + buffer = skb->data; /* copy the packet into the buffer */ d_link_setup_address(read_from, RW_ADDR); diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c index 7daab328e813..dff42384b141 100644 --- a/drivers/net/eexpress.c +++ b/drivers/net/eexpress.c @@ -511,7 +511,7 @@ eexp_send_packet(struct sk_buff *skb, struct device *dev) /* For ethernet, fill in the header. This should really be done by a higher level, rather than duplicated for each ethernet adaptor. */ - if (!skb->arp && dev->rebuild_header(skb+1, dev)) { + if (!skb->arp && dev->rebuild_header(skb->data, dev)) { skb->dev = dev; arp_queue (skb); return 0; @@ -523,7 +523,7 @@ eexp_send_packet(struct sk_buff *skb, struct device *dev) printk("%s: Transmitter access conflict.\n", dev->name); else { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = (void *)(skb+1); + unsigned char *buf = skb->data; /* Disable the 82586's input to the interrupt line. */ outb(irqrmap[dev->irq], ioaddr + SET_IRQ); @@ -960,7 +960,7 @@ eexp_rx(struct device *dev) outw(data_buffer_addr + 10, ioaddr + READ_PTR); - insw(ioaddr, (void *)(skb+1), (pkt_len + 1) >> 1); + insw(ioaddr, skb->data, (pkt_len + 1) >> 1); #ifdef HAVE_NETIF_RX netif_rx(skb); diff --git a/drivers/net/lance.c b/drivers/net/lance.c index d6c77ed4368b..1d610e88a7bb 100644 --- a/drivers/net/lance.c +++ b/drivers/net/lance.c @@ -512,7 +512,7 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev) } /* Fill in the ethernet header. */ - if (!skb->arp && dev->rebuild_header(skb+1, dev)) { + if (!skb->arp && dev->rebuild_header(skb->data, dev)) { skb->dev = dev; arp_queue (skb); return 0; @@ -553,11 +553,11 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev) /* If any part of this buffer is >16M we must copy it to a low-memory buffer. */ - if ((int)(skb+1) + skb->len > 0x01000000) { + if ((int)(skb->data) + skb->len > 0x01000000) { if (lance_debug > 5) printk("%s: bouncing a high-memory packet (%#x).\n", - dev->name, (int)(skb+1)); - memcpy(&lp->tx_bounce_buffs[entry], skb+1, skb->len); + dev->name, (int)skb->data); + memcpy(&lp->tx_bounce_buffs[entry], skb->data, skb->len); lp->tx_ring[entry].base = (int)(lp->tx_bounce_buffs + entry) | 0x83000000; if (skb->free) @@ -567,7 +567,7 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev) /* Gimme!!! */ if(skb->free==0) skb_kept_by_device(skb); - lp->tx_ring[entry].base = (int)(skb+1) | 0x83000000; + lp->tx_ring[entry].base = (int)skb->data | 0x83000000; } lp->cur_tx++; @@ -726,7 +726,7 @@ lance_rx(struct device *dev) skb->mem_addr = skb; skb->len = pkt_len; skb->dev = dev; - memcpy((unsigned char *) (skb + 1), + memcpy(skb->data, (unsigned char *)(lp->rx_ring[entry].base & 0x00ffffff), pkt_len); #ifdef HAVE_NETIF_RX diff --git a/drivers/net/plip.c b/drivers/net/plip.c index a676cfcc5ceb..39530dd58c5e 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -285,7 +285,7 @@ plip_tx_packet(struct sk_buff *skb, struct device *dev) /* Pretend we are an ethernet and fill in the header. This could use a simplified routine someday. */ - if (!skb->arp && dev->rebuild_header(skb+1, dev)) { + if (!skb->arp && dev->rebuild_header(skb->data, dev)) { skb->dev = dev; arp_queue (skb); return 0; @@ -293,7 +293,7 @@ plip_tx_packet(struct sk_buff *skb, struct device *dev) skb->arp=1; dev->trans_start = jiffies; - ret_val = plip_send_packet(dev, (unsigned char *)(skb+1), skb->len); + ret_val = plip_send_packet(dev, skb->data, skb->len); if (skb->free) kfree_skb (skb, FREE_WRITE); dev->tbusy = 0; @@ -483,8 +483,8 @@ plip_receive_packet(struct device *dev) } { /* phase of receiving the data */ - /* 'skb+1' points to the start of sk_buff data area. */ - unsigned char *buf = (unsigned char *) (skb+1); + /* 'skb->data' points to the start of sk_buff data area. */ + unsigned char *buf = skb->data; unsigned char *eth_p = (unsigned char *)ð int i; for ( i = 0; i < sizeof(eth); i++) { diff --git a/drivers/net/skeleton.c b/drivers/net/skeleton.c index 760ca94e05eb..b6d047bd5e51 100644 --- a/drivers/net/skeleton.c +++ b/drivers/net/skeleton.c @@ -316,7 +316,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev) /* For ethernet, fill in the header. This should really be done by a higher level, rather than duplicated for each ethernet adaptor. */ - if (!skb->arp && dev->rebuild_header(skb+1, dev)) { + if (!skb->arp && dev->rebuild_header(skb->data, dev)) { skb->dev = dev; arp_queue (skb); return 0; @@ -329,7 +329,7 @@ net_send_packet(struct sk_buff *skb, struct device *dev) printk("%s: Transmitter access conflict.\n", dev->name); else { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = (void *)(skb+1); + unsigned char *buf = skb->data; hardware_send_packet(ioaddr, buf, length); dev->trans_start = jiffies; @@ -420,11 +420,11 @@ net_rx(struct device *dev) skb->len = pkt_len; skb->dev = dev; - /* 'skb+1' points to the start of sk_buff data area. */ - memcpy((unsigned char *) (skb + 1), (void*)dev->rmem_start, + /* 'skb->data' points to the start of sk_buff data area. */ + memcpy(skb->data, (void*)dev->rmem_start, pkt_len); /* or */ - insw(ioaddr, (void *)(skb+1), (pkt_len + 1) >> 1); + insw(ioaddr, skb->data, (pkt_len + 1) >> 1); #ifdef HAVE_NETIF_RX netif_rx(skb); diff --git a/drivers/net/slip.c b/drivers/net/slip.c index f19a2260c8e9..514fa8ceb5ed 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -545,7 +545,7 @@ sl_xmit(struct sk_buff *skb, struct device *dev) #ifdef CONFIG_AX25 if(sl->mode & SL_MODE_AX25) { - if(!skb->arp && dev->rebuild_header(skb+1,dev)) + if(!skb->arp && dev->rebuild_header(skb->data,dev)) { skb->dev=dev; arp_queue(skb); @@ -555,8 +555,8 @@ sl_xmit(struct sk_buff *skb, struct device *dev) } #endif sl_lock(sl); -/* sl_hex_dump((unsigned char *)(skb+1),skb->len);*/ - sl_encaps(sl, (unsigned char *) (skb + 1), skb->len); +/* sl_hex_dump(skb->data,skb->len);*/ + sl_encaps(sl, skb->data, skb->len); if (skb->free) kfree_skb(skb, FREE_WRITE); } return(0); @@ -599,7 +599,7 @@ sl_add_arp(unsigned long addr, struct sk_buff *skb, struct device *dev) struct slip *sl=&sl_ctrl[dev->base_addr]; if(sl->mode&SL_MODE_AX25) - arp_add(addr,((char *)(skb+1))+8,dev); + arp_add(addr,((char *) skb->data)+8,dev); #endif } @@ -686,6 +686,10 @@ sl_open(struct device *dev) return(-ENOMEM); } + dev->flags|=IFF_UP; + /* Needed because address '0' is special */ + if(dev->pa_addr==0) + dev->pa_addr=ntohl(0xC0000001); DPRINTF((DBG_SLIP, "SLIP: channel %d opened.\n", sl->line)); return(0); } diff --git a/kernel/sched.c b/kernel/sched.c index 6d94afd86f7a..43c648953ebe 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -642,8 +642,8 @@ static void do_timer(struct pt_regs * regs) calc_load(); if ((VM_MASK & regs->eflags) || (3 & regs->cs)) { current->utime++; - if(current != task[0]) { - if(current->priority != 15) + if (current != task[0]) { + if (current->priority < 15) kstat.cpu_nice++; else kstat.cpu_user++; diff --git a/net/inet/arp.c b/net/inet/arp.c index 71384af13e42..789b817c6167 100644 --- a/net/inet/arp.c +++ b/net/inet/arp.c @@ -251,14 +251,19 @@ arp_send_q(void) /* Create and send our response to an ARP request. */ -static int -arp_response(struct arphdr *arp1, struct device *dev, int addrtype) + +/* + * We are now a bit smarter. We know the old buffer must be big enough + * so why allocate a new one for the reply ? + */ + +static int arp_response(struct sk_buff *skb,struct arphdr *arp1, struct device *dev, int addrtype) { struct arphdr *arp2; - struct sk_buff *skb; unsigned long src, dst; unsigned char *ptr1, *ptr2; int hlen; + int len; struct arp_table *apt = NULL;/* =NULL otherwise the compiler gives warnings */ /* Decode the source (REQUEST) message. */ @@ -270,24 +275,28 @@ arp_response(struct arphdr *arp1, struct device *dev, int addrtype) { apt=arp_lookup_proxy(dst); if(apt==NULL) + { + kfree_skb(skb,FREE_READ); return(1); + } } - /* Get some mem and initialize it for the return trip. */ - skb = alloc_skb(sizeof(struct sk_buff) + - sizeof(struct arphdr) + - (2 * arp1->ar_hln) + (2 * arp1->ar_pln) + - dev->hard_header_len, GFP_ATOMIC); - if (skb == NULL) { - printk("ARP: no memory available for ARP REPLY!\n"); - return(1); + skb->h.raw=skb->data; + skb->len+=dev->hard_header_len; /* Grow the packet back to its original form */ + + /* Can't check for exceeding the size - some people pad. */ + len= sizeof(struct arphdr) + (2 * arp1->ar_hln) + (2 * arp1->ar_pln) + dev->hard_header_len; + if(len>skb->len) + { + printk("Received runt ARP request!\n"); + kfree_skb(skb,FREE_READ); + return 1; } - skb->mem_addr = skb; - skb->len = sizeof(struct arphdr) + (2 * arp1->ar_hln) + - (2 * arp1->ar_pln) + dev->hard_header_len; - skb->mem_len = sizeof(struct sk_buff) + skb->len; + skb->len = len; + hlen = dev->hard_header(skb->data, dev, ETH_P_ARP, src, dst, skb->len); + if (hlen < 0) { printk("ARP: cannot create HW frame header for REPLY !\n"); kfree_skb(skb, FREE_WRITE); @@ -578,8 +587,7 @@ arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) * Yes, it is for us. * Allocate, fill in and send an ARP REPLY packet. */ - ret = arp_response(arp, dev, addr_hint); - kfree_skb(skb, FREE_READ); + ret = arp_response(skb,arp, dev, addr_hint); return(ret); } @@ -608,14 +616,12 @@ arp_send(unsigned long paddr, struct device *dev, unsigned long saddr) /* Fill in the request. */ skb->sk = NULL; - skb->mem_addr = skb; skb->len = sizeof(struct arphdr) + dev->hard_header_len + (2 * dev->addr_len) + 8; - skb->mem_len = sizeof(struct sk_buff) + skb->len; skb->arp = 1; skb->dev = dev; - skb->next = NULL; skb->free = 1; + skb->next = NULL; tmp = dev->hard_header(skb->data, dev, ETH_P_ARP, 0, saddr, skb->len); if (tmp < 0) { kfree_skb(skb,FREE_WRITE); diff --git a/net/inet/sock.c b/net/inet/sock.c index 643361dbac08..3de12e38f290 100644 --- a/net/inet/sock.c +++ b/net/inet/sock.c @@ -324,10 +324,10 @@ destroy_sock(struct sock *sk) delete_timer(sk); - if (sk->send_tmp != NULL) + while ((skb = tcp_dequeue_partial(sk)) != NULL) { - IS_SKB(sk->send_tmp); - kfree_skb(sk->send_tmp, FREE_WRITE); + IS_SKB(skb); + kfree_skb(skb, FREE_WRITE); } /* Cleanup up the write buffer. */ @@ -869,7 +869,7 @@ inet_create(struct socket *sock, int protocol) sk->state = TCP_CLOSE; sk->dead = 0; sk->ack_timed = 0; - sk->send_tmp = NULL; + sk->partial = NULL; sk->user_mss = 0; sk->debug = 0; diff --git a/net/inet/sock.h b/net/inet/sock.h index 2133f4db650f..3fb08a9a00d2 100644 --- a/net/inet/sock.h +++ b/net/inet/sock.h @@ -89,7 +89,8 @@ struct sock { struct sk_buff *volatile send_tail; struct sk_buff *volatile send_head; struct sk_buff *volatile back_log; - struct sk_buff *send_tmp; + struct sk_buff *partial; + struct timer_list partial_timer; long retransmits; struct sk_buff *volatile wback, *volatile wfront, diff --git a/net/inet/tcp.c b/net/inet/tcp.c index b0d60745488f..91f689ae38a8 100644 --- a/net/inet/tcp.c +++ b/net/inet/tcp.c @@ -648,43 +648,52 @@ static void tcp_send_skb(struct sock *sk, struct sk_buff *skb) } } -static struct sk_buff * dequeue_partial(struct sock * sk) +struct sk_buff * tcp_dequeue_partial(struct sock * sk) { struct sk_buff * skb; unsigned long flags; save_flags(flags); cli(); - skb = sk->send_tmp; - sk->send_tmp = NULL; + skb = sk->partial; + if (skb) { + sk->partial = NULL; + del_timer(&sk->partial_timer); + } restore_flags(flags); return skb; } -static void enqueue_partial(struct sk_buff * skb, struct sock * sk) +static void tcp_send_partial(struct sock *sk) +{ + struct sk_buff *skb; + + if (sk == NULL) + return; + while ((skb = tcp_dequeue_partial(sk)) != NULL) + tcp_send_skb(sk, skb); +} + +void tcp_enqueue_partial(struct sk_buff * skb, struct sock * sk) { struct sk_buff * tmp; unsigned long flags; save_flags(flags); cli(); - tmp = sk->send_tmp; - sk->send_tmp = skb; + tmp = sk->partial; + if (tmp) + del_timer(&sk->partial_timer); + sk->partial = skb; + sk->partial_timer.expires = 5*HZ; + sk->partial_timer.function = (void (*)(unsigned long)) tcp_send_partial; + sk->partial_timer.data = (unsigned long) sk; + add_timer(&sk->partial_timer); restore_flags(flags); if (tmp) tcp_send_skb(sk, tmp); } -static void tcp_send_partial(struct sock *sk) -{ - struct sk_buff *skb; - - if (sk == NULL) - return; - while ((skb = dequeue_partial(sk)) != NULL) - tcp_send_skb(sk, skb); -} - /* This routine sends an ack and also updates the window. */ static void @@ -897,7 +906,7 @@ tcp_write(struct sock *sk, unsigned char *from, */ /* Now we need to check if we have a half built packet. */ - if ((skb = dequeue_partial(sk)) != NULL) { + if ((skb = tcp_dequeue_partial(sk)) != NULL) { int hdrlen; /* IP header + TCP header */ @@ -920,10 +929,12 @@ tcp_write(struct sock *sk, unsigned char *from, len -= copy; sk->send_seq += copy; } - enqueue_partial(skb, sk); - if ((skb->len - hdrlen) >= sk->mss || (flags & MSG_OOB)) { - tcp_send_partial(sk); - } + if ((skb->len - hdrlen) >= sk->mss || + (flags & MSG_OOB) || + !sk->packets_out) + tcp_send_skb(sk, skb); + else + tcp_enqueue_partial(skb, sk); continue; } @@ -949,7 +960,8 @@ tcp_write(struct sock *sk, unsigned char *from, copy = min(copy, len); /* We should really check the window here also. */ - if (sk->packets_out && copy < sk->mss && !(flags & MSG_OOB)) { + send_tmp = NULL; + if (copy < sk->mss && !(flags & MSG_OOB)) { /* We will release the socket incase we sleep here. */ release_sock(sk); /* NB: following must be mtu, because mss can be increased. @@ -962,7 +974,6 @@ tcp_write(struct sock *sk, unsigned char *from, release_sock(sk); skb = prot->wmalloc(sk, copy + prot->max_header + sizeof(*skb), 0, GFP_KERNEL); sk->inuse = 1; - send_tmp = NULL; } /* If we didn't get any memory, we need to sleep. */ @@ -1041,8 +1052,8 @@ tcp_write(struct sock *sk, unsigned char *from, skb->free = 0; sk->send_seq += copy; - if (send_tmp != NULL) { - enqueue_partial(send_tmp, sk); + if (send_tmp != NULL && sk->packets_out) { + tcp_enqueue_partial(send_tmp, sk); continue; } tcp_send_skb(sk, skb); @@ -1057,7 +1068,7 @@ tcp_write(struct sock *sk, unsigned char *from, */ /* Avoid possible race on send_tmp - c/o Johannes Stille */ - if(sk->send_tmp && + if(sk->partial && ((!sk->packets_out) /* If not nagling we can send on the before case too.. */ || (sk->nonagle && before(sk->send_seq , sk->window_seq)) @@ -1585,7 +1596,8 @@ tcp_shutdown(struct sock *sk, int how) sk->inuse = 1; /* Clear out any half completed packets. */ - if (sk->send_tmp) tcp_send_partial(sk); + if (sk->partial) + tcp_send_partial(sk); prot =(struct proto *)sk->prot; th =(struct tcphdr *)&sk->dummy_th; @@ -1898,7 +1910,7 @@ tcp_conn_request(struct sock *sk, struct sk_buff *skb, newsk->intr = 0; newsk->proc = 0; newsk->done = 0; - newsk->send_tmp = NULL; + newsk->partial = NULL; newsk->pair = NULL; newsk->wmem_alloc = 0; newsk->rmem_alloc = 0; @@ -2081,7 +2093,7 @@ tcp_close(struct sock *sk, int timeout) sk->rqueue = NULL; /* Get rid off any half-completed packets. */ - if (sk->send_tmp) { + if (sk->partial) { tcp_send_partial(sk); } @@ -2565,7 +2577,7 @@ tcp_ack(struct sock *sk, struct tcphdr *th, unsigned long saddr, int len) } } - if (sk->packets_out == 0 && sk->send_tmp != NULL && + if (sk->packets_out == 0 && sk->partial != NULL && sk->wfront == NULL && sk->send_head == NULL) { flag |= 1; tcp_send_partial(sk); diff --git a/net/inet/tcp.h b/net/inet/tcp.h index bc952568f20c..007f3eee4ca7 100644 --- a/net/inet/tcp.h +++ b/net/inet/tcp.h @@ -124,5 +124,8 @@ extern int tcp_rcv(struct sk_buff *skb, struct device *dev, extern int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg); +extern void tcp_enqueue_partial(struct sk_buff *, struct sock *); +extern struct sk_buff * tcp_dequeue_partial(struct sock *); + #endif /* _TCP_H */ -- 2.39.5