diff options
Diffstat (limited to 'net')
69 files changed, 825 insertions, 383 deletions
diff --git a/net/9p/Kconfig b/net/9p/Kconfig index 71bc110aebf8..bafc50c9e6ff 100644 --- a/net/9p/Kconfig +++ b/net/9p/Kconfig @@ -23,6 +23,13 @@ config NET_9P_FD file descriptors. TCP/IP is the default transport for 9p, so if you are going to use 9p, you'll likely want this. +config NET_9P_VIRTIO + depends on NET_9P && EXPERIMENTAL && VIRTIO + tristate "9P Virtio Transport (Experimental)" + help + This builds support for a transports between + guest partitions and a host partition. + config NET_9P_DEBUG bool "Debug information" depends on NET_9P diff --git a/net/9p/Makefile b/net/9p/Makefile index 5059bc06f8f3..d3abb246ccab 100644 --- a/net/9p/Makefile +++ b/net/9p/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_NET_9P) := 9pnet.o obj-$(CONFIG_NET_9P_FD) += 9pnet_fd.o +obj-$(CONFIG_NET_9P_VIRTIO) += 9pnet_virtio.o 9pnet-objs := \ mod.o \ @@ -12,3 +13,6 @@ obj-$(CONFIG_NET_9P_FD) += 9pnet_fd.o 9pnet_fd-objs := \ trans_fd.o \ + +9pnet_virtio-objs := \ + trans_virtio.o \ diff --git a/net/9p/mux.c b/net/9p/mux.c index f14014793bed..c9f0805048e4 100644 --- a/net/9p/mux.c +++ b/net/9p/mux.c @@ -222,8 +222,10 @@ static int p9_mux_poll_start(struct p9_conn *m) } if (i >= ARRAY_SIZE(p9_mux_poll_tasks)) { - if (vptlast == NULL) + if (vptlast == NULL) { + mutex_unlock(&p9_mux_task_lock); return -ENOMEM; + } P9_DPRINTK(P9_DEBUG_MUX, "put in proc %d\n", i); list_add(&m->mux_list, &vptlast->mux_list); diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c new file mode 100644 index 000000000000..40b71a29fc3f --- /dev/null +++ b/net/9p/trans_virtio.c @@ -0,0 +1,353 @@ +/* + * The Guest 9p transport driver + * + * This is a trivial pipe-based transport driver based on the lguest console + * code: we use lguest's DMA mechanism to send bytes out, and register a + * DMA buffer to receive bytes in. It is assumed to be present and available + * from the very beginning of boot. + * + * This may be have been done by just instaniating another HVC console, + * but HVC's blocksize of 16 bytes is annoying and painful to performance. + * + * A more efficient transport could be built based on the virtio block driver + * but it requires some changes in the 9p transport model (which are in + * progress) + * + */ +/* + * Copyright (C) 2007 Eric Van Hensbergen, IBM Corporation + * + * Based on virtio console driver + * Copyright (C) 2006, 2007 Rusty Russell, IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to: + * Free Software Foundation + * 51 Franklin Street, Fifth Floor + * Boston, MA 02111-1301 USA + * + */ + +#include <linux/in.h> +#include <linux/module.h> +#include <linux/net.h> +#include <linux/ipv6.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/un.h> +#include <linux/uaccess.h> +#include <linux/inet.h> +#include <linux/idr.h> +#include <linux/file.h> +#include <net/9p/9p.h> +#include <linux/parser.h> +#include <net/9p/transport.h> +#include <linux/scatterlist.h> +#include <linux/virtio.h> +#include <linux/virtio_9p.h> + +/* a single mutex to manage channel initialization and attachment */ +static DECLARE_MUTEX(virtio_9p_lock); +/* global which tracks highest initialized channel */ +static int chan_index; + +/* We keep all per-channel information in a structure. + * This structure is allocated within the devices dev->mem space. + * A pointer to the structure will get put in the transport private. + */ +static struct virtio_chan { + bool initialized; /* channel is initialized */ + bool inuse; /* channel is in use */ + + struct virtqueue *in_vq, *out_vq; + struct virtio_device *vdev; + + /* This is our input buffer, and how much data is left in it. */ + unsigned int in_len; + char *in, *inbuf; + + wait_queue_head_t wq; /* waitq for buffer */ +} channels[MAX_9P_CHAN]; + +/* How many bytes left in this page. */ +static unsigned int rest_of_page(void *data) +{ + return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE); +} + +static int p9_virtio_write(struct p9_trans *trans, void *buf, int count) +{ + struct virtio_chan *chan = (struct virtio_chan *) trans->priv; + struct virtqueue *out_vq = chan->out_vq; + struct scatterlist sg[1]; + unsigned int len; + + P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio write (%d)\n", count); + + /* keep it simple - make sure we don't overflow a page */ + if (rest_of_page(buf) < count) + count = rest_of_page(buf); + + sg_init_one(sg, buf, count); + + /* add_buf wants a token to identify this buffer: we hand it any + * non-NULL pointer, since there's only ever one buffer. */ + if (out_vq->vq_ops->add_buf(out_vq, sg, 1, 0, (void *)1) == 0) { + /* Tell Host to go! */ + out_vq->vq_ops->kick(out_vq); + /* Chill out until it's done with the buffer. */ + while (!out_vq->vq_ops->get_buf(out_vq, &len)) + cpu_relax(); + } + + P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio wrote (%d)\n", count); + + /* We're expected to return the amount of data we wrote: all of it. */ + return count; +} + +/* Create a scatter-gather list representing our input buffer and put it in the + * queue. */ +static void add_inbuf(struct virtio_chan *chan) +{ + struct scatterlist sg[1]; + + sg_init_one(sg, chan->inbuf, PAGE_SIZE); + + /* We should always be able to add one buffer to an empty queue. */ + if (chan->in_vq->vq_ops->add_buf(chan->in_vq, sg, 0, 1, chan->inbuf)) + BUG(); + chan->in_vq->vq_ops->kick(chan->in_vq); +} + +static int p9_virtio_read(struct p9_trans *trans, void *buf, int count) +{ + struct virtio_chan *chan = (struct virtio_chan *) trans->priv; + struct virtqueue *in_vq = chan->in_vq; + + P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio read (%d)\n", count); + + /* If we don't have an input queue yet, we can't get input. */ + BUG_ON(!in_vq); + + /* No buffer? Try to get one. */ + if (!chan->in_len) { + chan->in = in_vq->vq_ops->get_buf(in_vq, &chan->in_len); + if (!chan->in) + return 0; + } + + /* You want more than we have to give? Well, try wanting less! */ + if (chan->in_len < count) + count = chan->in_len; + + /* Copy across to their buffer and increment offset. */ + memcpy(buf, chan->in, count); + chan->in += count; + chan->in_len -= count; + + /* Finished? Re-register buffer so Host will use it again. */ + if (chan->in_len == 0) + add_inbuf(chan); + + P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio finished read (%d)\n", + count); + + return count; +} + +/* The poll function is used by 9p transports to determine if there + * is there is activity available on a particular channel. In our case + * we use it to wait for a callback from the input routines. + */ +static unsigned int +p9_virtio_poll(struct p9_trans *trans, struct poll_table_struct *pt) +{ + struct virtio_chan *chan = (struct virtio_chan *)trans->priv; + struct virtqueue *in_vq = chan->in_vq; + int ret = POLLOUT; /* we can always handle more output */ + + poll_wait(NULL, &chan->wq, pt); + + /* No buffer? Try to get one. */ + if (!chan->in_len) + chan->in = in_vq->vq_ops->get_buf(in_vq, &chan->in_len); + + if (chan->in_len) + ret |= POLLIN; + + return ret; +} + +static void p9_virtio_close(struct p9_trans *trans) +{ + struct virtio_chan *chan = trans->priv; + + down(&virtio_9p_lock); + chan->inuse = false; + up(&virtio_9p_lock); + + kfree(trans); +} + +static bool p9_virtio_intr(struct virtqueue *q) +{ + struct virtio_chan *chan = q->vdev->priv; + + P9_DPRINTK(P9_DEBUG_TRANS, "9p poll_wakeup: %p\n", &chan->wq); + wake_up_interruptible(&chan->wq); + + return true; +} + +static int p9_virtio_probe(struct virtio_device *dev) +{ + int err; + struct virtio_chan *chan; + int index; + + down(&virtio_9p_lock); + index = chan_index++; + chan = &channels[index]; + up(&virtio_9p_lock); + + if (chan_index > MAX_9P_CHAN) { + printk(KERN_ERR "9p: virtio: Maximum channels exceeded\n"); + BUG(); + } + + chan->vdev = dev; + + /* This is the scratch page we use to receive console input */ + chan->inbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!chan->inbuf) { + err = -ENOMEM; + goto fail; + } + + /* Find the input queue. */ + dev->priv = chan; + chan->in_vq = dev->config->find_vq(dev, p9_virtio_intr); + if (IS_ERR(chan->in_vq)) { + err = PTR_ERR(chan->in_vq); + goto free; + } + + chan->out_vq = dev->config->find_vq(dev, NULL); + if (IS_ERR(chan->out_vq)) { + err = PTR_ERR(chan->out_vq); + goto free_in_vq; + } + + init_waitqueue_head(&chan->wq); + + /* Register the input buffer the first time. */ + add_inbuf(chan); + chan->inuse = false; + chan->initialized = true; + + return 0; + +free_in_vq: + dev->config->del_vq(chan->in_vq); +free: + kfree(chan->inbuf); +fail: + down(&virtio_9p_lock); + chan_index--; + up(&virtio_9p_lock); + return err; +} + +/* This sets up a transport channel for 9p communication. Right now + * we only match the first available channel, but eventually we couldlook up + * alternate channels by matching devname versus a virtio_config entry. + * We use a simple reference count mechanism to ensure that only a single + * mount has a channel open at a time. */ +static struct p9_trans *p9_virtio_create(const char *devname, char *args) +{ + struct p9_trans *trans; + int index = 0; + struct virtio_chan *chan = channels; + + down(&virtio_9p_lock); + while (index < MAX_9P_CHAN) { + if (chan->initialized && !chan->inuse) { + chan->inuse = true; + break; + } else { + index++; + chan = &channels[index]; + } + } + up(&virtio_9p_lock); + + if (index >= MAX_9P_CHAN) { + printk(KERN_ERR "9p: virtio: couldn't find a free channel\n"); + return NULL; + } + + trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL); + if (!trans) { + printk(KERN_ERR "9p: couldn't allocate transport\n"); + return ERR_PTR(-ENOMEM); + } + + trans->write = p9_virtio_write; + trans->read = p9_virtio_read; + trans->close = p9_virtio_close; + trans->poll = p9_virtio_poll; + trans->priv = chan; + + return trans; +} + +#define VIRTIO_ID_9P 9 + +static struct virtio_device_id id_table[] = { + { VIRTIO_ID_9P, VIRTIO_DEV_ANY_ID }, + { 0 }, +}; + +/* The standard "struct lguest_driver": */ +static struct virtio_driver p9_virtio_drv = { + .driver.name = KBUILD_MODNAME, + .driver.owner = THIS_MODULE, + .id_table = id_table, + .probe = p9_virtio_probe, +}; + +static struct p9_trans_module p9_virtio_trans = { + .name = "virtio", + .create = p9_virtio_create, + .maxsize = PAGE_SIZE, + .def = 0, +}; + +/* The standard init function */ +static int __init p9_virtio_init(void) +{ + int count; + + for (count = 0; count < MAX_9P_CHAN; count++) + channels[count].initialized = false; + + v9fs_register_trans(&p9_virtio_trans); + return register_virtio_driver(&p9_virtio_drv); +} + +module_init(p9_virtio_init); + +MODULE_DEVICE_TABLE(virtio, id_table); +MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>"); +MODULE_DESCRIPTION("Virtio 9p Transport"); +MODULE_LICENSE("GPL"); diff --git a/net/core/dev.c b/net/core/dev.c index 872658927e47..02e7d8377c4a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -120,6 +120,8 @@ #include <linux/ctype.h> #include <linux/if_arp.h> +#include "net-sysfs.h" + /* * The list of packet types we will receive (as opposed to discard) * and the routines to invoke. @@ -249,10 +251,6 @@ static RAW_NOTIFIER_HEAD(netdev_chain); DEFINE_PER_CPU(struct softnet_data, softnet_data); -extern int netdev_kobject_init(void); -extern int netdev_register_kobject(struct net_device *); -extern void netdev_unregister_kobject(struct net_device *); - #ifdef CONFIG_DEBUG_LOCK_ALLOC /* * register_netdevice() inits dev->_xmit_lock and sets lockdep class @@ -885,6 +883,9 @@ int dev_change_name(struct net_device *dev, char *newname) if (!dev_valid_name(newname)) return -EINVAL; + if (strncmp(newname, dev->name, IFNAMSIZ) == 0) + return 0; + memcpy(oldname, dev->name, IFNAMSIZ); if (strchr(newname, '%')) { @@ -1007,17 +1008,20 @@ int dev_open(struct net_device *dev) * Call device private open method */ set_bit(__LINK_STATE_START, &dev->state); - if (dev->open) { + + if (dev->validate_addr) + ret = dev->validate_addr(dev); + + if (!ret && dev->open) ret = dev->open(dev); - if (ret) - clear_bit(__LINK_STATE_START, &dev->state); - } /* * If it went open OK then: */ - if (!ret) { + if (ret) + clear_bit(__LINK_STATE_START, &dev->state); + else { /* * Set the flags. */ @@ -1038,6 +1042,7 @@ int dev_open(struct net_device *dev) */ call_netdevice_notifiers(NETDEV_UP, dev); } + return ret; } @@ -2167,7 +2172,15 @@ static void net_rx_action(struct softirq_action *h) weight = n->weight; - work = n->poll(n, weight); + /* This NAPI_STATE_SCHED test is for avoiding a race + * with netpoll's poll_napi(). Only the entity which + * obtains the lock and sees NAPI_STATE_SCHED set will + * actually make the ->poll() call. Therefore we avoid + * accidently calling ->poll() when NAPI is not scheduled. + */ + work = 0; + if (test_bit(NAPI_STATE_SCHED, &n->state)) + work = n->poll(n, weight); WARN_ON_ONCE(work > weight); @@ -2663,7 +2676,7 @@ static void __net_exit dev_proc_net_exit(struct net *net) proc_net_remove(net, "dev"); } -static struct pernet_operations __net_initdata dev_proc_ops = { +static struct pernet_operations dev_proc_ops = { .init = dev_proc_net_init, .exit = dev_proc_net_exit, }; @@ -4323,7 +4336,7 @@ static void __net_exit netdev_exit(struct net *net) kfree(net->dev_index_head); } -static struct pernet_operations __net_initdata netdev_net_ops = { +static struct pernet_operations netdev_net_ops = { .init = netdev_init, .exit = netdev_exit, }; @@ -4354,7 +4367,7 @@ static void __net_exit default_device_exit(struct net *net) rtnl_unlock(); } -static struct pernet_operations __net_initdata default_device_ops = { +static struct pernet_operations default_device_ops = { .exit = default_device_exit, }; diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index 15241cf48af8..ae354057d84c 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c @@ -285,7 +285,7 @@ static void __net_exit dev_mc_net_exit(struct net *net) proc_net_remove(net, "dev_mcast"); } -static struct pernet_operations __net_initdata dev_mc_net_ops = { +static struct pernet_operations dev_mc_net_ops = { .init = dev_mc_net_init, .exit = dev_mc_net_exit, }; diff --git a/net/core/flow.c b/net/core/flow.c index 0ab5234b17d8..3ed2b4b1d6d4 100644 --- a/net/core/flow.c +++ b/net/core/flow.c @@ -142,8 +142,6 @@ typedef u64 flow_compare_t; typedef u32 flow_compare_t; #endif -extern void flowi_is_missized(void); - /* I hear what you're saying, use memcmp. But memcmp cannot make * important assumptions that we can here, such as alignment and * constant size. @@ -153,8 +151,7 @@ static int flow_key_compare(struct flowi *key1, struct flowi *key2) flow_compare_t *k1, *k1_lim, *k2; const int n_elem = sizeof(struct flowi) / sizeof(flow_compare_t); - if (sizeof(struct flowi) % sizeof(flow_compare_t)) - flowi_is_missized(); + BUILD_BUG_ON(sizeof(struct flowi) % sizeof(flow_compare_t)); k1 = (flow_compare_t *) key1; k1_lim = k1 + n_elem; diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 6628e457ddc0..61ead1d11132 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -18,6 +18,8 @@ #include <linux/wireless.h> #include <net/iw_handler.h> +#include "net-sysfs.h" + #ifdef CONFIG_SYSFS static const char fmt_hex[] = "%#x\n"; static const char fmt_long_hex[] = "%#lx\n"; diff --git a/net/core/net-sysfs.h b/net/core/net-sysfs.h new file mode 100644 index 000000000000..f5f108db3924 --- /dev/null +++ b/net/core/net-sysfs.h @@ -0,0 +1,8 @@ +#ifndef __NET_SYSFS_H__ +#define __NET_SYSFS_H__ + +int netdev_kobject_init(void); +int netdev_register_kobject(struct net_device *); +void netdev_unregister_kobject(struct net_device *); + +#endif diff --git a/net/core/netpoll.c b/net/core/netpoll.c index bf8d18f1b013..c499b5c69bed 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -116,6 +116,29 @@ static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh, * network adapter, forcing superfluous retries and possibly timeouts. * Thus, we set our budget to greater than 1. */ +static int poll_one_napi(struct netpoll_info *npinfo, + struct napi_struct *napi, int budget) +{ + int work; + + /* net_rx_action's ->poll() invocations and our's are + * synchronized by this test which is only made while + * holding the napi->poll_lock. + */ + if (!test_bit(NAPI_STATE_SCHED, &napi->state)) + return budget; + + npinfo->rx_flags |= NETPOLL_RX_DROP; + atomic_inc(&trapped); + + work = napi->poll(napi, budget); + + atomic_dec(&trapped); + npinfo->rx_flags &= ~NETPOLL_RX_DROP; + + return budget - work; +} + static void poll_napi(struct netpoll *np) { struct netpoll_info *npinfo = np->dev->npinfo; @@ -123,17 +146,13 @@ static void poll_napi(struct netpoll *np) int budget = 16; list_for_each_entry(napi, &np->dev->napi_list, dev_list) { - if (test_bit(NAPI_STATE_SCHED, &napi->state) && - napi->poll_owner != smp_processor_id() && + if (napi->poll_owner != smp_processor_id() && spin_trylock(&napi->poll_lock)) { - npinfo->rx_flags |= NETPOLL_RX_DROP; - atomic_inc(&trapped); - - napi->poll(napi, budget); - - atomic_dec(&trapped); - npinfo->rx_flags &= ~NETPOLL_RX_DROP; + budget = poll_one_napi(npinfo, napi, budget); spin_unlock(&napi->poll_lock); + + if (!budget) + break; } } } diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 4a2640d38261..e1ba26fb4bf2 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -742,7 +742,7 @@ static struct net *get_net_ns_by_pid(pid_t pid) /* Lookup the network namespace */ net = ERR_PTR(-ESRCH); rcu_read_lock(); - tsk = find_task_by_pid(pid); + tsk = find_task_by_vpid(pid); if (tsk) { struct nsproxy *nsproxy; nsproxy = task_nsproxy(tsk); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 4e2c84fcf276..573e17240197 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -415,13 +415,6 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; n->nohdr = 0; n->destructor = NULL; -#ifdef CONFIG_NET_CLS_ACT - /* FIXME What is this and why don't we do it in copy_skb_header? */ - n->tc_verd = SET_TC_VERD(n->tc_verd,0); - n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd); - n->tc_verd = CLR_TC_MUNGED(n->tc_verd); - C(iif); -#endif C(truesize); atomic_set(&n->users, 1); C(head); @@ -2045,9 +2038,7 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) if (copy > 0) { if (copy > len) copy = len; - sg_set_page(&sg[elt], virt_to_page(skb->data + offset)); - sg[elt].offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; - sg[elt].length = copy; + sg_set_buf(sg, skb->data + offset, copy); elt++; if ((len -= copy) == 0) return elt; @@ -2065,9 +2056,8 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) if (copy > len) copy = len; - sg_set_page(&sg[elt], frag->page); - sg[elt].offset = frag->page_offset+offset-start; - sg[elt].length = copy; + sg_set_page(&sg[elt], frag->page, copy, + frag->page_offset+offset-start); elt++; if (!(len -= copy)) return elt; diff --git a/net/core/sock.c b/net/core/sock.c index febbcbcf8022..bba9949681ff 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1649,7 +1649,6 @@ void sock_enable_timestamp(struct sock *sk) net_enable_timestamp(); } } -EXPORT_SYMBOL(sock_enable_timestamp); /* * Get a socket option on an socket. diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 6d5ea9762040..113cc728dc31 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -9,25 +9,12 @@ #include <linux/sysctl.h> #include <linux/module.h> #include <linux/socket.h> +#include <linux/netdevice.h> #include <net/sock.h> +#include <net/xfrm.h> #ifdef CONFIG_SYSCTL -extern int netdev_max_backlog; -extern int weight_p; - -extern __u32 sysctl_wmem_max; -extern __u32 sysctl_rmem_max; - -extern int sysctl_core_destroy_delay; - -#ifdef CONFIG_XFRM -extern u32 sysctl_xfrm_aevent_etime; -extern u32 sysctl_xfrm_aevent_rseqth; -extern int sysctl_xfrm_larval_drop; -extern u32 sysctl_xfrm_acq_expires; -#endif - ctl_table core_table[] = { #ifdef CONFIG_NET { diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 426008e3b7e3..d694656b8800 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -750,20 +750,16 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) */ hctx->ccid2hctx_ssthresh = ~0; hctx->ccid2hctx_numdupack = 3; - hctx->ccid2hctx_seqbufc = 0; /* XXX init ~ to window size... */ if (ccid2_hc_tx_alloc_seq(hctx)) return -ENOMEM; - hctx->ccid2hctx_sent = 0; hctx->ccid2hctx_rto = 3 * HZ; ccid2_change_srtt(hctx, -1); hctx->ccid2hctx_rttvar = -1; - hctx->ccid2hctx_lastrtt = 0; hctx->ccid2hctx_rpdupack = -1; hctx->ccid2hctx_last_cong = jiffies; - hctx->ccid2hctx_high_ack = 0; hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire; hctx->ccid2hctx_rtotimer.data = (unsigned long)sk; diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 25772c326172..19b33586333d 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -40,6 +40,8 @@ #include "lib/tfrc.h" #include "ccid3.h" +#include <asm/unaligned.h> + #ifdef CONFIG_IP_DCCP_CCID3_DEBUG static int ccid3_debug; #define ccid3_pr_debug(format, a...) DCCP_PR_DEBUG(ccid3_debug, format, ##a) @@ -544,6 +546,7 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, const struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); struct ccid3_options_received *opt_recv; + __be32 opt_val; opt_recv = &hctx->ccid3hctx_options_received; @@ -563,8 +566,8 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, dccp_role(sk), sk, len); rc = -EINVAL; } else { - opt_recv->ccid3or_loss_event_rate = - ntohl(*(__be32 *)value); + opt_val = get_unaligned((__be32 *)value); + opt_recv->ccid3or_loss_event_rate = ntohl(opt_val); ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n", dccp_role(sk), sk, opt_recv->ccid3or_loss_event_rate); @@ -585,8 +588,8 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, dccp_role(sk), sk, len); rc = -EINVAL; } else { - opt_recv->ccid3or_receive_rate = - ntohl(*(__be32 *)value); + opt_val = get_unaligned((__be32 *)value); + opt_recv->ccid3or_receive_rate = ntohl(opt_val); ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n", dccp_role(sk), sk, opt_recv->ccid3or_receive_rate); @@ -601,8 +604,6 @@ static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk) { struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid); - hctx->ccid3hctx_s = 0; - hctx->ccid3hctx_rtt = 0; hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; INIT_LIST_HEAD(&hctx->ccid3hctx_hist); @@ -963,8 +964,6 @@ static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk) INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist); hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack = ktime_get_real(); - hcrx->ccid3hcrx_s = 0; - hcrx->ccid3hcrx_rtt = 0; return 0; } diff --git a/net/dccp/input.c b/net/dccp/input.c index 3560a2a875a0..1ce101062824 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -58,6 +58,42 @@ static void dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb) dccp_send_close(sk, 0); } +static u8 dccp_reset_code_convert(const u8 code) +{ + const u8 error_code[] = { + [DCCP_RESET_CODE_CLOSED] = 0, /* normal termination */ + [DCCP_RESET_CODE_UNSPECIFIED] = 0, /* nothing known */ + [DCCP_RESET_CODE_ABORTED] = ECONNRESET, + + [DCCP_RESET_CODE_NO_CONNECTION] = ECONNREFUSED, + [DCCP_RESET_CODE_CONNECTION_REFUSED] = ECONNREFUSED, + [DCCP_RESET_CODE_TOO_BUSY] = EUSERS, + [DCCP_RESET_CODE_AGGRESSION_PENALTY] = EDQUOT, + + [DCCP_RESET_CODE_PACKET_ERROR] = ENOMSG, + [DCCP_RESET_CODE_BAD_INIT_COOKIE] = EBADR, + [DCCP_RESET_CODE_BAD_SERVICE_CODE] = EBADRQC, + [DCCP_RESET_CODE_OPTION_ERROR] = EILSEQ, + [DCCP_RESET_CODE_MANDATORY_ERROR] = EOPNOTSUPP, + }; + + return code >= DCCP_MAX_RESET_CODES ? 0 : error_code[code]; +} + +static void dccp_rcv_reset(struct sock *sk, struct sk_buff *skb) +{ + u8 err = dccp_reset_code_convert(dccp_hdr_reset(skb)->dccph_reset_code); + + sk->sk_err = err; + + /* Queue the equivalent of TCP fin so that dccp_recvmsg exits the loop */ + dccp_fin(sk, skb); + + if (err && !sock_flag(sk, SOCK_DEAD)) + sk_wake_async(sk, 0, POLL_ERR); + dccp_time_wait(sk, DCCP_TIME_WAIT, 0); +} + static void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); @@ -191,9 +227,8 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb, * S.state := TIMEWAIT * Set TIMEWAIT timer * Drop packet and return - */ - dccp_fin(sk, skb); - dccp_time_wait(sk, DCCP_TIME_WAIT, 0); + */ + dccp_rcv_reset(sk, skb); return 0; case DCCP_PKT_CLOSEREQ: dccp_rcv_closereq(sk, skb); @@ -521,12 +556,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, * Drop packet and return */ if (dh->dccph_type == DCCP_PKT_RESET) { - /* - * Queue the equivalent of TCP fin so that dccp_recvmsg - * exits the loop - */ - dccp_fin(sk, skb); - dccp_time_wait(sk, DCCP_TIME_WAIT, 0); + dccp_rcv_reset(sk, skb); return 0; /* * Step 7: Check for unexpected packet types diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 222549ab274a..01a6a808bdb7 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -241,8 +241,8 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) goto out; dp = dccp_sk(sk); - seq = dccp_hdr_seq(skb); - if (sk->sk_state != DCCP_LISTEN && + seq = dccp_hdr_seq(dh); + if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) && !between48(seq, dp->dccps_swl, dp->dccps_swh)) { NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS); goto out; @@ -795,7 +795,7 @@ static int dccp_v4_rcv(struct sk_buff *skb) dh = dccp_hdr(skb); - DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb); + DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(dh); DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type; dccp_pr_debug("%8.8s " diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index bbadd6681b83..62428ff137dd 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -173,7 +173,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, icmpv6_err_convert(type, code, &err); - seq = DCCP_SKB_CB(skb)->dccpd_seq; + seq = dccp_hdr_seq(dh); /* Might be for an request_sock */ switch (sk->sk_state) { struct request_sock *req, **prev; @@ -787,7 +787,7 @@ static int dccp_v6_rcv(struct sk_buff *skb) dh = dccp_hdr(skb); - DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb); + DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(dh); DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type; if (dccp_packet_without_ack(skb)) diff --git a/net/dccp/options.c b/net/dccp/options.c index d361b5533309..d286cffe2c49 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -14,6 +14,7 @@ #include <linux/dccp.h> #include <linux/module.h> #include <linux/types.h> +#include <asm/unaligned.h> #include <linux/kernel.h> #include <linux/skbuff.h> @@ -59,6 +60,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) unsigned char opt, len; unsigned char *value; u32 elapsed_time; + __be32 opt_val; int rc; int mandatory = 0; @@ -145,7 +147,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) if (len != 4) goto out_invalid_option; - opt_recv->dccpor_timestamp = ntohl(*(__be32 *)value); + opt_val = get_unaligned((__be32 *)value); + opt_recv->dccpor_timestamp = ntohl(opt_val); dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp; dp->dccps_timestamp_time = ktime_get_real(); @@ -159,7 +162,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) if (len != 4 && len != 6 && len != 8) goto out_invalid_option; - opt_recv->dccpor_timestamp_echo = ntohl(*(__be32 *)value); + opt_val = get_unaligned((__be32 *)value); + opt_recv->dccpor_timestamp_echo = ntohl(opt_val); dccp_pr_debug("%s rx opt: TIMESTAMP_ECHO=%u, len=%d, " "ackno=%llu", dccp_role(sk), @@ -168,16 +172,20 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) (unsigned long long) DCCP_SKB_CB(skb)->dccpd_ack_seq); + value += 4; - if (len == 4) { + if (len == 4) { /* no elapsed time included */ dccp_pr_debug_cat("\n"); break; } - if (len == 6) - elapsed_time = ntohs(*(__be16 *)(value + 4)); - else - elapsed_time = ntohl(*(__be32 *)(value + 4)); + if (len == 6) { /* 2-byte elapsed time */ + __be16 opt_val2 = get_unaligned((__be16 *)value); + elapsed_time = ntohs(opt_val2); + } else { /* 4-byte elapsed time */ + opt_val = get_unaligned((__be32 *)value); + elapsed_time = ntohl(opt_val); + } dccp_pr_debug_cat(", ELAPSED_TIME=%u\n", elapsed_time); @@ -192,10 +200,13 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) if (pkt_type == DCCP_PKT_DATA) continue; - if (len == 2) - elapsed_time = ntohs(*(__be16 *)value); - else - elapsed_time = ntohl(*(__be32 *)value); + if (len == 2) { + __be16 opt_val2 = get_unaligned((__be16 *)value); + elapsed_time = ntohs(opt_val2); + } else { + opt_val = get_unaligned((__be32 *)value); + elapsed_time = ntohl(opt_val); + } if (elapsed_time > opt_recv->dccpor_elapsed_time) opt_recv->dccpor_elapsed_time = elapsed_time; diff --git a/net/dccp/proto.c b/net/dccp/proto.c index cc9bf1cb2646..d84973928033 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -26,6 +26,7 @@ #include <net/sock.h> #include <net/xfrm.h> +#include <asm/ioctls.h> #include <asm/semaphore.h> #include <linux/spinlock.h> #include <linux/timer.h> @@ -378,8 +379,36 @@ EXPORT_SYMBOL_GPL(dccp_poll); int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg) { - dccp_pr_debug("entry\n"); - return -ENOIOCTLCMD; + int rc = -ENOTCONN; + + lock_sock(sk); + + if (sk->sk_state == DCCP_LISTEN) + goto out; + + switch (cmd) { + case SIOCINQ: { + struct sk_buff *skb; + unsigned long amount = 0; + + skb = skb_peek(&sk->sk_receive_queue); + if (skb != NULL) { + /* + * We will only return the amount of this packet since + * that is all that will be read. + */ + amount = skb->len; + } + rc = put_user(amount, (int __user *)arg); + } + break; + default: + rc = -ENOIOCTLCMD; + break; + } +out: + release_sock(sk); + return rc; } EXPORT_SYMBOL_GPL(dccp_ioctl); diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index ed8a3d49487d..6b2e454ae313 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -298,6 +298,14 @@ static int eth_change_mtu(struct net_device *dev, int new_mtu) return 0; } +static int eth_validate_addr(struct net_device *dev) +{ + if (!is_valid_ether_addr(dev->dev_addr)) + return -EINVAL; + + return 0; +} + const struct header_ops eth_header_ops ____cacheline_aligned = { .create = eth_header, .parse = eth_header_parse, @@ -317,6 +325,7 @@ void ether_setup(struct net_device *dev) dev->change_mtu = eth_change_mtu; dev->set_mac_address = eth_mac_addr; + dev->validate_addr = eth_validate_addr; dev->type = ARPHRD_ETHER; dev->hard_header_len = ETH_HLEN; diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c index c796661a021b..4cce3534e408 100644 --- a/net/ieee80211/ieee80211_crypt_tkip.c +++ b/net/ieee80211/ieee80211_crypt_tkip.c @@ -14,6 +14,7 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/random.h> +#include <linux/scatterlist.h> #include <linux/skbuff.h> #include <linux/netdevice.h> #include <linux/mm.h> @@ -24,7 +25,7 @@ #include <net/ieee80211.h> #include <linux/crypto.h> -#include <asm/scatterlist.h> +#include <linux/scatterlist.h> #include <linux/crc32.h> MODULE_AUTHOR("Jouni Malinen"); @@ -536,13 +537,8 @@ static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr, return -1; } sg_init_table(sg, 2); - sg_set_page(&sg[0], virt_to_page(hdr)); - sg[0].offset = offset_in_page(hdr); - sg[0].length = 16; - - sg_set_page(&sg[1], virt_to_page(data)); - sg[1].offset = offset_in_page(data); - sg[1].length = data_len; + sg_set_buf(&sg[0], hdr, 16); + sg_set_buf(&sg[1], data, data_len); if (crypto_hash_setkey(tfm_michael, key, 8)) return -1; diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c index 0af6103d715c..866fc04c44f9 100644 --- a/net/ieee80211/ieee80211_crypt_wep.c +++ b/net/ieee80211/ieee80211_crypt_wep.c @@ -14,6 +14,7 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/random.h> +#include <linux/scatterlist.h> #include <linux/skbuff.h> #include <linux/mm.h> #include <asm/string.h> @@ -21,7 +22,7 @@ #include <net/ieee80211.h> #include <linux/crypto.h> -#include <asm/scatterlist.h> +#include <linux/scatterlist.h> #include <linux/crc32.h> MODULE_AUTHOR("Jouni Malinen"); diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 805a78e6ed55..f18e88bc86ec 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -504,22 +504,16 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) INIT_RCU_HEAD(&doi_def->rcu); INIT_LIST_HEAD(&doi_def->dom_list); - rcu_read_lock(); - if (cipso_v4_doi_search(doi_def->doi) != NULL) - goto doi_add_failure_rlock; spin_lock(&cipso_v4_doi_list_lock); if (cipso_v4_doi_search(doi_def->doi) != NULL) - goto doi_add_failure_slock; + goto doi_add_failure; list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list); spin_unlock(&cipso_v4_doi_list_lock); - rcu_read_unlock(); return 0; -doi_add_failure_slock: +doi_add_failure: spin_unlock(&cipso_v4_doi_list_lock); -doi_add_failure_rlock: - rcu_read_unlock(); return -EEXIST; } @@ -543,29 +537,23 @@ int cipso_v4_doi_remove(u32 doi, struct cipso_v4_doi *doi_def; struct cipso_v4_domhsh_entry *dom_iter; - rcu_read_lock(); - if (cipso_v4_doi_search(doi) != NULL) { - spin_lock(&cipso_v4_doi_list_lock); - doi_def = cipso_v4_doi_search(doi); - if (doi_def == NULL) { - spin_unlock(&cipso_v4_doi_list_lock); - rcu_read_unlock(); - return -ENOENT; - } + spin_lock(&cipso_v4_doi_list_lock); + doi_def = cipso_v4_doi_search(doi); + if (doi_def != NULL) { doi_def->valid = 0; list_del_rcu(&doi_def->list); spin_unlock(&cipso_v4_doi_list_lock); + rcu_read_lock(); list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list) if (dom_iter->valid) netlbl_domhsh_remove(dom_iter->domain, audit_info); - cipso_v4_cache_invalidate(); rcu_read_unlock(); - + cipso_v4_cache_invalidate(); call_rcu(&doi_def->rcu, callback); return 0; } - rcu_read_unlock(); + spin_unlock(&cipso_v4_doi_list_lock); return -ENOENT; } @@ -653,22 +641,19 @@ int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain) new_dom->valid = 1; INIT_RCU_HEAD(&new_dom->rcu); - rcu_read_lock(); spin_lock(&cipso_v4_doi_list_lock); - list_for_each_entry_rcu(iter, &doi_def->dom_list, list) + list_for_each_entry(iter, &doi_def->dom_list, list) if (iter->valid && ((domain != NULL && iter->domain != NULL && strcmp(iter->domain, domain) == 0) || (domain == NULL && iter->domain == NULL))) { spin_unlock(&cipso_v4_doi_list_lock); - rcu_read_unlock(); kfree(new_dom->domain); kfree(new_dom); return -EEXIST; } list_add_tail_rcu(&new_dom->list, &doi_def->dom_list); spin_unlock(&cipso_v4_doi_list_lock); - rcu_read_unlock(); return 0; } @@ -689,9 +674,8 @@ int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, { struct cipso_v4_domhsh_entry *iter; - rcu_read_lock(); spin_lock(&cipso_v4_doi_list_lock); - list_for_each_entry_rcu(iter, &doi_def->dom_list, list) + list_for_each_entry(iter, &doi_def->dom_list, list) if (iter->valid && ((domain != NULL && iter->domain != NULL && strcmp(iter->domain, domain) == 0) || @@ -699,13 +683,10 @@ int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, iter->valid = 0; list_del_rcu(&iter->list); spin_unlock(&cipso_v4_doi_list_lock); - rcu_read_unlock(); call_rcu(&iter->rcu, cipso_v4_doi_domhsh_free); - return 0; } spin_unlock(&cipso_v4_doi_list_lock); - rcu_read_unlock(); return -ENOENT; } diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 6b1a31a74cf2..cad4278025ad 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -3,7 +3,7 @@ #include <net/ip.h> #include <net/xfrm.h> #include <net/esp.h> -#include <asm/scatterlist.h> +#include <linux/scatterlist.h> #include <linux/crypto.h> #include <linux/kernel.h> #include <linux/pfkeyv2.h> @@ -110,7 +110,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) if (!sg) goto unlock; } - skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen); + sg_init_table(sg, nfrags); + sg_mark_end(sg, skb_to_sgvec(skb, sg, esph->enc_data + + esp->conf.ivlen - + skb->data, clen)); err = crypto_blkcipher_encrypt(&desc, sg, sg, clen); if (unlikely(sg != &esp->sgbuf[0])) kfree(sg); @@ -201,7 +204,9 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) if (!sg) goto out; } - skb_to_sgvec(skb, sg, sizeof(*esph) + esp->conf.ivlen, elen); + sg_init_table(sg, nfrags); + sg_mark_end(sg, skb_to_sgvec(skb, sg, sizeof(*esph) + esp->conf.ivlen, + elen)); err = crypto_blkcipher_decrypt(&desc, sg, sg, elen); if (unlikely(sg != &esp->sgbuf[0])) kfree(sg); diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 78b514ba1414..60123905dbbf 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -128,13 +128,14 @@ struct net_device * ip_dev_find(__be32 addr) struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } }; struct fib_result res; struct net_device *dev = NULL; + struct fib_table *local_table; #ifdef CONFIG_IP_MULTIPLE_TABLES res.r = NULL; #endif - if (!ip_fib_local_table || - ip_fib_local_table->tb_lookup(ip_fib_local_table, &fl, &res)) + local_table = fib_get_table(RT_TABLE_LOCAL); + if (!local_table || local_table->tb_lookup(local_table, &fl, &res)) return NULL; if (res.type != RTN_LOCAL) goto out; @@ -152,6 +153,7 @@ unsigned inet_addr_type(__be32 addr) struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } }; struct fib_result res; unsigned ret = RTN_BROADCAST; + struct fib_table *local_table; if (ZERONET(addr) || BADCLASS(addr)) return RTN_BROADCAST; @@ -162,10 +164,10 @@ unsigned inet_addr_type(__be32 addr) res.r = NULL; #endif - if (ip_fib_local_table) { + local_table = fib_get_table(RT_TABLE_LOCAL); + if (local_table) { ret = RTN_UNICAST; - if (!ip_fib_local_table->tb_lookup(ip_fib_local_table, - &fl, &res)) { + if (!local_table->tb_lookup(local_table, &fl, &res)) { ret = res.type; fib_res_put(&res); } diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 272c69e106e9..233de0634298 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -1104,5 +1104,4 @@ void __init icmp_init(struct net_proto_family *ops) EXPORT_SYMBOL(icmp_err_convert); EXPORT_SYMBOL(icmp_send); EXPORT_SYMBOL(icmp_statistics); -EXPORT_SYMBOL(icmpmsg_statistics); EXPORT_SYMBOL(xrlim_allow); diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index f151900efaf9..02b02a8d681c 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -674,7 +674,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) struct rtable *rt; /* Route to the other host */ struct net_device *tdev; /* Device to other host */ struct iphdr *iph; /* Our new IP header */ - int max_headroom; /* The extra header space needed */ + unsigned int max_headroom; /* The extra header space needed */ int gre_hlen; __be32 dst; int mtu; @@ -1033,7 +1033,6 @@ static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu) return 0; } -#ifdef CONFIG_NET_IPGRE_BROADCAST /* Nice toy. Unfortunately, useless in real life :-) It allows to construct virtual multiprotocol broadcast "LAN" over the Internet, provided multicast routing is tuned. @@ -1092,10 +1091,19 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev, return -t->hlen; } +static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) +{ + struct iphdr *iph = (struct iphdr*) skb_mac_header(skb); + memcpy(haddr, &iph->saddr, 4); + return 4; +} + static const struct header_ops ipgre_header_ops = { .create = ipgre_header, + .parse = ipgre_header_parse, }; +#ifdef CONFIG_NET_IPGRE_BROADCAST static int ipgre_open(struct net_device *dev) { struct ip_tunnel *t = netdev_priv(dev); @@ -1197,6 +1205,8 @@ static int ipgre_tunnel_init(struct net_device *dev) dev->stop = ipgre_close; } #endif + } else { + dev->header_ops = &ipgre_header_ops; } if (!tdev && tunnel->parms.link) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index f508835ba713..e5f7dc2de303 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -161,7 +161,7 @@ static inline int ip_finish_output2(struct sk_buff *skb) struct dst_entry *dst = skb->dst; struct rtable *rt = (struct rtable *)dst; struct net_device *dev = dst->dev; - int hh_len = LL_RESERVED_SPACE(dev); + unsigned int hh_len = LL_RESERVED_SPACE(dev); if (rt->rt_type == RTN_MULTICAST) IP_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS); diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 5cd5bbe1379a..8c2b2b0741da 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -515,7 +515,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) struct net_device *tdev; /* Device to other host */ struct iphdr *old_iph = ip_hdr(skb); struct iphdr *iph; /* Our new IP header */ - int max_headroom; /* The extra header space needed */ + unsigned int max_headroom; /* The extra header space needed */ __be32 dst = tiph->daddr; int mtu; diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c index c99f2a33fb9e..0d4d9721cbd4 100644 --- a/net/ipv4/ipvs/ip_vs_sync.c +++ b/net/ipv4/ipvs/ip_vs_sync.c @@ -72,7 +72,6 @@ struct ip_vs_sync_thread_data { int state; }; -#define IP_VS_SYNC_CONN_TIMEOUT (3*60*HZ) #define SIMPLE_CONN_SIZE (sizeof(struct ip_vs_sync_conn)) #define FULL_CONN_SIZE \ (sizeof(struct ip_vs_sync_conn) + sizeof(struct ip_vs_sync_conn_options)) @@ -284,6 +283,7 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) struct ip_vs_sync_conn *s; struct ip_vs_sync_conn_options *opt; struct ip_vs_conn *cp; + struct ip_vs_protocol *pp; char *p; int i; @@ -342,7 +342,8 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) p += SIMPLE_CONN_SIZE; atomic_set(&cp->in_pkts, sysctl_ip_vs_sync_threshold[0]); - cp->timeout = IP_VS_SYNC_CONN_TIMEOUT; + pp = ip_vs_proto_get(s->protocol); + cp->timeout = pp->timeout_table[cp->state]; ip_vs_conn_put(cp); if (p > buffer+buflen) { diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c index d0a92dec1050..7c074e386c17 100644 --- a/net/ipv4/ipvs/ip_vs_xmit.c +++ b/net/ipv4/ipvs/ip_vs_xmit.c @@ -325,7 +325,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, __be16 df = old_iph->frag_off; sk_buff_data_t old_transport_header = skb->transport_header; struct iphdr *iph; /* Our new IP header */ - int max_headroom; /* The extra header space needed */ + unsigned int max_headroom; /* The extra header space needed */ int mtu; EnterFunction(10); diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index fa97947c6ae1..9aca9c55687c 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -128,7 +128,7 @@ config IP_NF_MATCH_ADDRTYPE eg. UNICAST, LOCAL, BROADCAST, ... If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. If unsure, say `N'. + <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. # `filter', generic and specific targets config IP_NF_FILTER @@ -371,7 +371,7 @@ config IP_NF_RAW and OUTPUT chains. If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. If unsure, say `N'. + <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. # ARP tables config IP_NF_ARPTABLES diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index fd16cb8f8abe..ffdccc0972e0 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -121,14 +121,6 @@ static const struct snmp_mib snmp4_ipextstats_list[] = { SNMP_MIB_SENTINEL }; -static const struct snmp_mib snmp4_icmp_list[] = { - SNMP_MIB_ITEM("InMsgs", ICMP_MIB_INMSGS), - SNMP_MIB_ITEM("InErrors", ICMP_MIB_INERRORS), - SNMP_MIB_ITEM("OutMsgs", ICMP_MIB_OUTMSGS), - SNMP_MIB_ITEM("OutErrors", ICMP_MIB_OUTERRORS), - SNMP_MIB_SENTINEL -}; - static struct { char *name; int index; @@ -312,7 +304,7 @@ static void icmp_put(struct seq_file *seq) for (i=0; icmpmibmap[i].name != NULL; i++) seq_printf(seq, " %lu", snmp_fold_field((void **) icmpmsg_statistics, - icmpmibmap[i].index)); + icmpmibmap[i].index | 0x100)); } /* diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 2e6ad6dbba6c..c64072bb504b 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2453,7 +2453,7 @@ void __init tcp_init(void) 0, &tcp_hashinfo.ehash_size, NULL, - 0); + thash_entries ? 0 : 512 * 1024); tcp_hashinfo.ehash_size = 1 << tcp_hashinfo.ehash_size; for (i = 0; i < tcp_hashinfo.ehash_size; i++) { rwlock_init(&tcp_hashinfo.ehash[i].lock); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 9288220b73a8..69d8c38ccd39 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -103,7 +103,7 @@ int sysctl_tcp_abc __read_mostly; #define FLAG_SLOWPATH 0x100 /* Do not skip RFC checks for window update.*/ #define FLAG_ONLY_ORIG_SACKED 0x200 /* SACKs only non-rexmit sent before RTO */ #define FLAG_SND_UNA_ADVANCED 0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */ -#define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained DSACK info */ +#define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained D-SACK info */ #define FLAG_NONHEAD_RETRANS_ACKED 0x1000 /* Non-head rexmitted data was ACKed */ #define FLAG_ACKED (FLAG_DATA_ACKED|FLAG_SYN_ACKED) @@ -866,7 +866,7 @@ static void tcp_disable_fack(struct tcp_sock *tp) tp->rx_opt.sack_ok &= ~2; } -/* Take a notice that peer is sending DSACKs */ +/* Take a notice that peer is sending D-SACKs */ static void tcp_dsack_seen(struct tcp_sock *tp) { tp->rx_opt.sack_ok |= 4; @@ -1058,7 +1058,7 @@ static void tcp_update_reordering(struct sock *sk, const int metric, * * With D-SACK the lower bound is extended to cover sequence space below * SND.UNA down to undo_marker, which is the last point of interest. Yet - * again, DSACK block must not to go across snd_una (for the same reason as + * again, D-SACK block must not to go across snd_una (for the same reason as * for the normal SACK blocks, explained above). But there all simplicity * ends, TCP might receive valid D-SACKs below that. As long as they reside * fully below undo_marker they do not affect behavior in anyway and can @@ -1080,7 +1080,7 @@ static int tcp_is_sackblock_valid(struct tcp_sock *tp, int is_dsack, if (!before(start_seq, tp->snd_nxt)) return 0; - /* In outstanding window? ...This is valid exit for DSACKs too. + /* In outstanding window? ...This is valid exit for D-SACKs too. * start_seq == snd_una is non-sensical (see comments above) */ if (after(start_seq, tp->snd_una)) @@ -1204,8 +1204,8 @@ static int tcp_check_dsack(struct tcp_sock *tp, struct sk_buff *ack_skb, * which may fail and creates some hassle (caller must handle error case * returns). */ -int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb, - u32 start_seq, u32 end_seq) +static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb, + u32 start_seq, u32 end_seq) { int in_sack, err; unsigned int pkt_len; @@ -1248,6 +1248,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ int cached_fack_count; int i; int first_sack_index; + int force_one_sack; if (!tp->sacked_out) { if (WARN_ON(tp->fackets_out)) @@ -1272,18 +1273,18 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ * if the only SACK change is the increase of the end_seq of * the first block then only apply that SACK block * and use retrans queue hinting otherwise slowpath */ - flag = 1; + force_one_sack = 1; for (i = 0; i < num_sacks; i++) { __be32 start_seq = sp[i].start_seq; __be32 end_seq = sp[i].end_seq; if (i == 0) { if (tp->recv_sack_cache[i].start_seq != start_seq) - flag = 0; + force_one_sack = 0; } else { if ((tp->recv_sack_cache[i].start_seq != start_seq) || (tp->recv_sack_cache[i].end_seq != end_seq)) - flag = 0; + force_one_sack = 0; } tp->recv_sack_cache[i].start_seq = start_seq; tp->recv_sack_cache[i].end_seq = end_seq; @@ -1295,7 +1296,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ } first_sack_index = 0; - if (flag) + if (force_one_sack) num_sacks = 1; else { int j; @@ -1321,9 +1322,6 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ } } - /* clear flag as used for different purpose in following code */ - flag = 0; - /* Use SACK fastpath hint if valid */ cached_skb = tp->fastpath_skb_hint; cached_fack_count = tp->fastpath_cnt_hint; @@ -1615,7 +1613,7 @@ void tcp_enter_frto(struct sock *sk) !icsk->icsk_retransmits)) { tp->prior_ssthresh = tcp_current_ssthresh(sk); /* Our state is too optimistic in ssthresh() call because cwnd - * is not reduced until tcp_enter_frto_loss() when previous FRTO + * is not reduced until tcp_enter_frto_loss() when previous F-RTO * recovery has not yet completed. Pattern would be this: RTO, * Cumulative ACK, RTO (2xRTO for the same segment does not end * up here twice). @@ -1801,7 +1799,7 @@ void tcp_enter_loss(struct sock *sk, int how) tcp_set_ca_state(sk, TCP_CA_Loss); tp->high_seq = tp->snd_nxt; TCP_ECN_queue_cwr(tp); - /* Abort FRTO algorithm if one is in progress */ + /* Abort F-RTO algorithm if one is in progress */ tp->frto_counter = 0; } @@ -1946,7 +1944,7 @@ static int tcp_time_to_recover(struct sock *sk) struct tcp_sock *tp = tcp_sk(sk); __u32 packets_out; - /* Do not perform any recovery during FRTO algorithm */ + /* Do not perform any recovery during F-RTO algorithm */ if (tp->frto_counter) return 0; @@ -2962,7 +2960,7 @@ static int tcp_process_frto(struct sock *sk, int flag) } if (tp->frto_counter == 1) { - /* Sending of the next skb must be allowed or no FRTO */ + /* Sending of the next skb must be allowed or no F-RTO */ if (!tcp_send_head(sk) || after(TCP_SKB_CB(tcp_send_head(sk))->end_seq, tp->snd_una + tp->snd_wnd)) { @@ -3909,7 +3907,7 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, while (before(start, end)) { struct sk_buff *nskb; - int header = skb_headroom(skb); + unsigned int header = skb_headroom(skb); int copy = SKB_MAX_ORDER(header, 0); /* Too big header? This can happen with IPv6. */ diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 38cf73a56731..d3d8d5dfcee3 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -858,16 +858,16 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, u8 *newkey, u8 newkeylen) { /* Add Key to the list */ - struct tcp4_md5sig_key *key; + struct tcp_md5sig_key *key; struct tcp_sock *tp = tcp_sk(sk); struct tcp4_md5sig_key *keys; - key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr); + key = tcp_v4_md5_do_lookup(sk, addr); if (key) { /* Pre-existing entry - just update that one. */ - kfree(key->base.key); - key->base.key = newkey; - key->base.keylen = newkeylen; + kfree(key->key); + key->key = newkey; + key->keylen = newkeylen; } else { struct tcp_md5sig_info *md5sig; @@ -1055,6 +1055,9 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, bp->pad = 0; bp->protocol = protocol; bp->len = htons(tcplen); + + sg_init_table(sg, 4); + sg_set_buf(&sg[block++], bp, sizeof(*bp)); nbytes += sizeof(*bp); @@ -1080,6 +1083,8 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, sg_set_buf(&sg[block++], key->key, key->keylen); nbytes += key->keylen; + sg_mark_end(sg, block); + /* Now store the Hash into the packet */ err = crypto_hash_init(desc); if (err) diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c index b49dedcda52d..007304e99842 100644 --- a/net/ipv4/tcp_vegas.c +++ b/net/ipv4/tcp_vegas.c @@ -266,26 +266,25 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, */ diff = (old_wnd << V_PARAM_SHIFT) - target_cwnd; - if (tp->snd_cwnd <= tp->snd_ssthresh) { - /* Slow start. */ - if (diff > gamma) { - /* Going too fast. Time to slow down - * and switch to congestion avoidance. - */ - tp->snd_ssthresh = 2; - - /* Set cwnd to match the actual rate - * exactly: - * cwnd = (actual rate) * baseRTT - * Then we add 1 because the integer - * truncation robs us of full link - * utilization. - */ - tp->snd_cwnd = min(tp->snd_cwnd, - (target_cwnd >> - V_PARAM_SHIFT)+1); + if (diff > gamma && tp->snd_ssthresh > 2 ) { + /* Going too fast. Time to slow down + * and switch to congestion avoidance. + */ + tp->snd_ssthresh = 2; + + /* Set cwnd to match the actual rate + * exactly: + * cwnd = (actual rate) * baseRTT + * Then we add 1 because the integer + * truncation robs us of full link + * utilization. + */ + tp->snd_cwnd = min(tp->snd_cwnd, + (target_cwnd >> + V_PARAM_SHIFT)+1); - } + } else if (tp->snd_cwnd <= tp->snd_ssthresh) { + /* Slow start. */ tcp_slow_start(tp); } else { /* Congestion avoidance. */ diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 35d2b0e9e10b..4bc25b46f33f 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1152,7 +1152,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable); sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest, - skb->dev->ifindex, udptable ); + inet_iif(skb), udptable); if (sk != NULL) { int ret = udp_queue_rcv_skb(sk, skb); diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 72a659806cad..ab17b5e62355 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -29,7 +29,7 @@ #include <net/ip.h> #include <net/xfrm.h> #include <net/esp.h> -#include <asm/scatterlist.h> +#include <linux/scatterlist.h> #include <linux/crypto.h> #include <linux/kernel.h> #include <linux/pfkeyv2.h> @@ -109,7 +109,10 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) if (!sg) goto unlock; } - skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen); + sg_init_table(sg, nfrags); + sg_mark_end(sg, skb_to_sgvec(skb, sg, esph->enc_data + + esp->conf.ivlen - + skb->data, clen)); err = crypto_blkcipher_encrypt(&desc, sg, sg, clen); if (unlikely(sg != &esp->sgbuf[0])) kfree(sg); @@ -205,7 +208,10 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) goto out; } } - skb_to_sgvec(skb, sg, sizeof(*esph) + esp->conf.ivlen, elen); + sg_init_table(sg, nfrags); + sg_mark_end(sg, skb_to_sgvec(skb, sg, + sizeof(*esph) + esp->conf.ivlen, + elen)); ret = crypto_blkcipher_decrypt(&desc, sg, sg, elen); if (unlikely(sg != &esp->sgbuf[0])) kfree(sg); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 13565dfb1b45..653fc0a8235b 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -171,7 +171,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, u32 mtu; if (opt) { - int head_room; + unsigned int head_room; /* First: exthdrs may take lots of space (~8K for now) MAX_HEADER is not enough. diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 2320cc27ff9e..5383b33db8ca 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -838,7 +838,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, struct dst_entry *dst; struct net_device *tdev; int mtu; - int max_headroom = sizeof(struct ipv6hdr); + unsigned int max_headroom = sizeof(struct ipv6hdr); u8 proto; int err = -1; int pkt_len; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 20cfc90d5597..36f7dbfb6dbb 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1670,7 +1670,7 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * f filp, buffer, lenp, ppos); else if ((strcmp(ctl->procname, "retrans_time_ms") == 0) || - (strcmp(ctl->procname, "base_reacable_time_ms") == 0)) + (strcmp(ctl->procname, "base_reachable_time_ms") == 0)) ret = proc_dointvec_ms_jiffies(ctl, write, filp, buffer, lenp, ppos); else diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 466657a9a8bd..71433d29d884 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -430,7 +430,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) struct rtable *rt; /* Route to the other host */ struct net_device *tdev; /* Device to other host */ struct iphdr *iph; /* Our new IP header */ - int max_headroom; /* The extra header space needed */ + unsigned int max_headroom; /* The extra header space needed */ __be32 dst = tiph->daddr; int mtu; struct in6_addr *addr6; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 737b755342bd..f1523b82cac1 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -59,6 +59,7 @@ #include <net/snmp.h> #include <net/dsfield.h> #include <net/timewait_sock.h> +#include <net/netdma.h> #include <asm/uaccess.h> @@ -560,16 +561,16 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, char *newkey, u8 newkeylen) { /* Add key to the list */ - struct tcp6_md5sig_key *key; + struct tcp_md5sig_key *key; struct tcp_sock *tp = tcp_sk(sk); struct tcp6_md5sig_key *keys; - key = (struct tcp6_md5sig_key*) tcp_v6_md5_do_lookup(sk, peer); + key = tcp_v6_md5_do_lookup(sk, peer); if (key) { /* modify existing entry - just update that one */ - kfree(key->base.key); - key->base.key = newkey; - key->base.keylen = newkeylen; + kfree(key->key); + key->key = newkey; + key->keylen = newkeylen; } else { /* reallocate new list if current one is full. */ if (!tp->md5sig_info) { @@ -757,6 +758,8 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, bp->len = htonl(tcplen); bp->protocol = htonl(protocol); + sg_init_table(sg, 4); + sg_set_buf(&sg[block++], bp, sizeof(*bp)); nbytes += sizeof(*bp); @@ -778,6 +781,8 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, sg_set_buf(&sg[block++], key->key, key->keylen); nbytes += key->keylen; + sg_mark_end(sg, block); + /* Now store the hash into the packet */ err = crypto_hash_init(desc); if (err) { @@ -1728,6 +1733,8 @@ process: if (!sock_owned_by_user(sk)) { #ifdef CONFIG_NET_DMA struct tcp_sock *tp = tcp_sk(sk); + if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) + tp->ucopy.dma_chan = get_softnet_dma(); if (tp->ucopy.dma_chan) ret = tcp_v6_do_rcv(sk, skb); else diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 3d241e415a2a..1120b150e211 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -77,7 +77,7 @@ static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len, #endif /* CONFIG_PROC_FS */ static struct tty_driver *driver; -hashbin_t *ircomm_tty = NULL; +static hashbin_t *ircomm_tty = NULL; static const struct tty_operations ops = { .open = ircomm_tty_open, diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index f7ffeec3913f..fda0e06453e8 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -1184,7 +1184,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x " "status=%d aid=%d)\n", dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa), - capab_info, status_code, aid & ~(BIT(15) | BIT(14))); + capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); if (status_code != WLAN_STATUS_SUCCESS) { printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", @@ -2096,7 +2096,8 @@ static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta, { int tmp, hidden_ssid; - if (!memcmp(ifsta->ssid, ssid, ssid_len)) + if (ssid_len == ifsta->ssid_len && + !memcmp(ifsta->ssid, ssid, ssid_len)) return 1; if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index cc806d640f7a..a84a23310ff4 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -16,7 +16,7 @@ #include <linux/crypto.h> #include <linux/err.h> #include <linux/mm.h> -#include <asm/scatterlist.h> +#include <linux/scatterlist.h> #include <net/mac80211.h> #include "ieee80211_i.h" diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index d7a600a5720a..21a9fcc03796 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -363,7 +363,7 @@ config NETFILTER_XT_TARGET_TRACE the tables, chains, rules. If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. If unsure, say `N'. + <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. config NETFILTER_XT_TARGET_SECMARK tristate '"SECMARK" target support' diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 4d6171bc0829..000c2fb462d0 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -999,7 +999,7 @@ struct hlist_head *nf_ct_alloc_hashtable(int *sizep, int *vmalloced) *vmalloced = 0; size = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_head)); - hash = (void*)__get_free_pages(GFP_KERNEL, + hash = (void*)__get_free_pages(GFP_KERNEL|__GFP_NOWARN, get_order(sizeof(struct hlist_head) * size)); if (!hash) { diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index b6c844b7e1c1..b3675bd7db33 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -178,11 +178,9 @@ int netlbl_domhsh_init(u32 size) for (iter = 0; iter < hsh_tbl->size; iter++) INIT_LIST_HEAD(&hsh_tbl->tbl[iter]); - rcu_read_lock(); spin_lock(&netlbl_domhsh_lock); rcu_assign_pointer(netlbl_domhsh, hsh_tbl); spin_unlock(&netlbl_domhsh_lock); - rcu_read_unlock(); return 0; } @@ -222,7 +220,6 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, entry->valid = 1; INIT_RCU_HEAD(&entry->rcu); - ret_val = 0; rcu_read_lock(); if (entry->domain != NULL) { bkt = netlbl_domhsh_hash(entry->domain); @@ -233,7 +230,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, else ret_val = -EEXIST; spin_unlock(&netlbl_domhsh_lock); - } else if (entry->domain == NULL) { + } else { INIT_LIST_HEAD(&entry->list); spin_lock(&netlbl_domhsh_def_lock); if (rcu_dereference(netlbl_domhsh_def) == NULL) @@ -241,9 +238,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, else ret_val = -EEXIST; spin_unlock(&netlbl_domhsh_def_lock); - } else - ret_val = -EINVAL; - + } audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info); if (audit_buf != NULL) { audit_log_format(audit_buf, @@ -262,7 +257,6 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0); audit_log_end(audit_buf); } - rcu_read_unlock(); if (ret_val != 0) { @@ -313,38 +307,30 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) struct audit_buffer *audit_buf; rcu_read_lock(); - if (domain != NULL) - entry = netlbl_domhsh_search(domain, 0); - else - entry = netlbl_domhsh_search(domain, 1); + entry = netlbl_domhsh_search(domain, (domain != NULL ? 0 : 1)); if (entry == NULL) goto remove_return; switch (entry->type) { - case NETLBL_NLTYPE_UNLABELED: - break; case NETLBL_NLTYPE_CIPSOV4: - ret_val = cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4, - entry->domain); - if (ret_val != 0) - goto remove_return; + cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4, + entry->domain); break; } - ret_val = 0; if (entry != rcu_dereference(netlbl_domhsh_def)) { spin_lock(&netlbl_domhsh_lock); if (entry->valid) { entry->valid = 0; list_del_rcu(&entry->list); - } else - ret_val = -ENOENT; + ret_val = 0; + } spin_unlock(&netlbl_domhsh_lock); } else { spin_lock(&netlbl_domhsh_def_lock); if (entry->valid) { entry->valid = 0; rcu_assign_pointer(netlbl_domhsh_def, NULL); - } else - ret_val = -ENOENT; + ret_val = 0; + } spin_unlock(&netlbl_domhsh_def_lock); } @@ -357,11 +343,10 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) audit_log_end(audit_buf); } - if (ret_val == 0) - call_rcu(&entry->rcu, netlbl_domhsh_free_entry); - remove_return: rcu_read_unlock(); + if (ret_val == 0) + call_rcu(&entry->rcu, netlbl_domhsh_free_entry); return ret_val; } diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index 5315dacc5222..56483377997a 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -85,11 +85,9 @@ static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = { */ void netlbl_mgmt_protocount_inc(void) { - rcu_read_lock(); spin_lock(&netlabel_mgmt_protocount_lock); netlabel_mgmt_protocount++; spin_unlock(&netlabel_mgmt_protocount_lock); - rcu_read_unlock(); } /** @@ -103,12 +101,10 @@ void netlbl_mgmt_protocount_inc(void) */ void netlbl_mgmt_protocount_dec(void) { - rcu_read_lock(); spin_lock(&netlabel_mgmt_protocount_lock); if (netlabel_mgmt_protocount > 0) netlabel_mgmt_protocount--; spin_unlock(&netlabel_mgmt_protocount_lock); - rcu_read_unlock(); } /** diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 5c303c68af1d..348292450deb 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -84,12 +84,10 @@ static void netlbl_unlabel_acceptflg_set(u8 value, struct audit_buffer *audit_buf; u8 old_val; - rcu_read_lock(); - old_val = netlabel_unlabel_acceptflg; spin_lock(&netlabel_unlabel_acceptflg_lock); + old_val = netlabel_unlabel_acceptflg; netlabel_unlabel_acceptflg = value; spin_unlock(&netlabel_unlabel_acceptflg_lock); - rcu_read_unlock(); audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW, audit_info); diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 98e313e5e594..4f994c0fb3f8 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1565,7 +1565,11 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, netlink_dump(sk); sock_put(sk); - return 0; + + /* We successfully started a dump, by returning -EINTR we + * signal not to send ACK even if it was requested. + */ + return -EINTR; } void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) @@ -1619,17 +1623,21 @@ int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, /* Only requests are handled by the kernel */ if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) - goto skip; + goto ack; /* Skip control messages */ if (nlh->nlmsg_type < NLMSG_MIN_TYPE) - goto skip; + goto ack; err = cb(skb, nlh); -skip: + if (err == -EINTR) + goto skip; + +ack: if (nlh->nlmsg_flags & NLM_F_ACK || err) netlink_ack(skb, nlh, err); +skip: msglen = NLMSG_ALIGN(nlh->nlmsg_len); if (msglen > skb->len) msglen = skb->len; @@ -1880,7 +1888,7 @@ static void __net_exit netlink_net_exit(struct net *net) #endif } -static struct pernet_operations __net_initdata netlink_net_ops = { +static struct pernet_operations netlink_net_ops = { .init = netlink_net_init, .exit = netlink_net_exit, }; diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c index ac3cabdca78c..eebefb6ef139 100644 --- a/net/rxrpc/rxkad.c +++ b/net/rxrpc/rxkad.c @@ -135,9 +135,8 @@ static void rxkad_prime_packet_security(struct rxrpc_connection *conn) tmpbuf.x[2] = 0; tmpbuf.x[3] = htonl(conn->security_ix); - memset(sg, 0, sizeof(sg)); - sg_set_buf(&sg[0], &tmpbuf, sizeof(tmpbuf)); - sg_set_buf(&sg[1], &tmpbuf, sizeof(tmpbuf)); + sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf)); + sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf)); crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf)); memcpy(&conn->csum_iv, &tmpbuf.x[2], sizeof(conn->csum_iv)); @@ -180,9 +179,8 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call, desc.info = iv.x; desc.flags = 0; - memset(sg, 0, sizeof(sg)); - sg_set_buf(&sg[0], &tmpbuf, sizeof(tmpbuf)); - sg_set_buf(&sg[1], &tmpbuf, sizeof(tmpbuf)); + sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf)); + sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf)); crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf)); memcpy(sechdr, &tmpbuf, sizeof(tmpbuf)); @@ -227,9 +225,8 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, desc.info = iv.x; desc.flags = 0; - memset(sg, 0, sizeof(sg[0]) * 2); - sg_set_buf(&sg[0], sechdr, sizeof(rxkhdr)); - sg_set_buf(&sg[1], &rxkhdr, sizeof(rxkhdr)); + sg_init_one(&sg[0], sechdr, sizeof(rxkhdr)); + sg_init_one(&sg[1], &rxkhdr, sizeof(rxkhdr)); crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(rxkhdr)); /* we want to encrypt the skbuff in-place */ @@ -240,7 +237,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, len = data_size + call->conn->size_align - 1; len &= ~(call->conn->size_align - 1); - skb_to_sgvec(skb, sg, 0, len); + sg_init_table(sg, skb_to_sgvec(skb, sg, 0, len)); crypto_blkcipher_encrypt_iv(&desc, sg, sg, len); _leave(" = 0"); @@ -290,9 +287,8 @@ static int rxkad_secure_packet(const struct rxrpc_call *call, tmpbuf.x[0] = sp->hdr.callNumber; tmpbuf.x[1] = x; - memset(&sg, 0, sizeof(sg)); - sg_set_buf(&sg[0], &tmpbuf, sizeof(tmpbuf)); - sg_set_buf(&sg[1], &tmpbuf, sizeof(tmpbuf)); + sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf)); + sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf)); crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf)); x = ntohl(tmpbuf.x[1]); @@ -332,20 +328,23 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call, struct rxrpc_skb_priv *sp; struct blkcipher_desc desc; struct rxrpc_crypt iv; - struct scatterlist sg[2]; + struct scatterlist sg[16]; struct sk_buff *trailer; u32 data_size, buf; u16 check; + int nsg; _enter(""); sp = rxrpc_skb(skb); /* we want to decrypt the skbuff in-place */ - if (skb_cow_data(skb, 0, &trailer) < 0) + nsg = skb_cow_data(skb, 0, &trailer); + if (nsg < 0 || nsg > 16) goto nomem; - skb_to_sgvec(skb, sg, 0, 8); + sg_init_table(sg, nsg); + sg_mark_end(sg, skb_to_sgvec(skb, sg, 0, 8)); /* start the decryption afresh */ memset(&iv, 0, sizeof(iv)); @@ -426,7 +425,8 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call, goto nomem; } - skb_to_sgvec(skb, sg, 0, skb->len); + sg_init_table(sg, nsg); + sg_mark_end(sg, skb_to_sgvec(skb, sg, 0, skb->len)); /* decrypt from the session key */ payload = call->conn->key->payload.data; @@ -521,9 +521,8 @@ static int rxkad_verify_packet(const struct rxrpc_call *call, tmpbuf.x[0] = call->call_id; tmpbuf.x[1] = x; - memset(&sg, 0, sizeof(sg)); - sg_set_buf(&sg[0], &tmpbuf, sizeof(tmpbuf)); - sg_set_buf(&sg[1], &tmpbuf, sizeof(tmpbuf)); + sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf)); + sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf)); crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf)); x = ntohl(tmpbuf.x[1]); @@ -690,16 +689,20 @@ static void rxkad_calc_response_checksum(struct rxkad_response *response) static void rxkad_sg_set_buf2(struct scatterlist sg[2], void *buf, size_t buflen) { + int nsg = 1; - memset(sg, 0, sizeof(sg)); + sg_init_table(sg, 2); sg_set_buf(&sg[0], buf, buflen); if (sg[0].offset + buflen > PAGE_SIZE) { /* the buffer was split over two pages */ sg[0].length = PAGE_SIZE - sg[0].offset; sg_set_buf(&sg[1], buf + sg[0].length, buflen - sg[0].length); + nsg++; } + sg_mark_end(sg, nsg); + ASSERTCMP(sg[0].length + sg[1].length, ==, buflen); } @@ -712,7 +715,7 @@ static void rxkad_encrypt_response(struct rxrpc_connection *conn, { struct blkcipher_desc desc; struct rxrpc_crypt iv; - struct scatterlist ssg[2], dsg[2]; + struct scatterlist sg[2]; /* continue encrypting from where we left off */ memcpy(&iv, s2->session_key, sizeof(iv)); @@ -720,9 +723,8 @@ static void rxkad_encrypt_response(struct rxrpc_connection *conn, desc.info = iv.x; desc.flags = 0; - rxkad_sg_set_buf2(ssg, &resp->encrypted, sizeof(resp->encrypted)); - memcpy(dsg, ssg, sizeof(dsg)); - crypto_blkcipher_encrypt_iv(&desc, dsg, ssg, sizeof(resp->encrypted)); + rxkad_sg_set_buf2(sg, &resp->encrypted, sizeof(resp->encrypted)); + crypto_blkcipher_encrypt_iv(&desc, sg, sg, sizeof(resp->encrypted)); } /* @@ -817,7 +819,7 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn, { struct blkcipher_desc desc; struct rxrpc_crypt iv, key; - struct scatterlist ssg[1], dsg[1]; + struct scatterlist sg[1]; struct in_addr addr; unsigned life; time_t issue, now; @@ -850,9 +852,8 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn, desc.info = iv.x; desc.flags = 0; - sg_init_one(&ssg[0], ticket, ticket_len); - memcpy(dsg, ssg, sizeof(dsg)); - crypto_blkcipher_decrypt_iv(&desc, dsg, ssg, ticket_len); + sg_init_one(&sg[0], ticket, ticket_len); + crypto_blkcipher_decrypt_iv(&desc, sg, sg, ticket_len); p = ticket; end = p + ticket_len; @@ -961,7 +962,7 @@ static void rxkad_decrypt_response(struct rxrpc_connection *conn, const struct rxrpc_crypt *session_key) { struct blkcipher_desc desc; - struct scatterlist ssg[2], dsg[2]; + struct scatterlist sg[2]; struct rxrpc_crypt iv; _enter(",,%08x%08x", @@ -979,9 +980,8 @@ static void rxkad_decrypt_response(struct rxrpc_connection *conn, desc.info = iv.x; desc.flags = 0; - rxkad_sg_set_buf2(ssg, &resp->encrypted, sizeof(resp->encrypted)); - memcpy(dsg, ssg, sizeof(dsg)); - crypto_blkcipher_decrypt_iv(&desc, dsg, ssg, sizeof(resp->encrypted)); + rxkad_sg_set_buf2(sg, &resp->encrypted, sizeof(resp->encrypted)); + crypto_blkcipher_decrypt_iv(&desc, sg, sg, sizeof(resp->encrypted)); mutex_unlock(&rxkad_ci_mutex); _leave(""); diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index fd7bca4d5c20..c3fde9180f9d 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c @@ -166,7 +166,7 @@ bad_mirred: return TC_ACT_SHOT; } - skb2 = skb_clone(skb, GFP_ATOMIC); + skb2 = skb_act_clone(skb, GFP_ATOMIC); if (skb2 == NULL) goto bad_mirred; if (m->tcfm_eaction != TCA_EGRESS_MIRROR && diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index abd82fc3ec60..de894096e442 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -136,7 +136,7 @@ prio_dequeue(struct Qdisc* sch) * pulling an skb. This way we avoid excessive requeues * for slower queues. */ - if (!netif_subqueue_stopped(sch->dev, (q->mq ? prio : 0))) { + if (!__netif_subqueue_stopped(sch->dev, (q->mq ? prio : 0))) { qdisc = q->queues[prio]; skb = qdisc->dequeue(qdisc); if (skb) { @@ -165,7 +165,7 @@ static struct sk_buff *rr_dequeue(struct Qdisc* sch) * for slower queues. If the queue is stopped, try the * next queue. */ - if (!netif_subqueue_stopped(sch->dev, + if (!__netif_subqueue_stopped(sch->dev, (q->mq ? q->curband : 0))) { qdisc = q->queues[q->curband]; skb = qdisc->dequeue(qdisc); diff --git a/net/sctp/auth.c b/net/sctp/auth.c index cbd64b216cce..6d5fa6bb371b 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -107,7 +107,7 @@ struct sctp_shared_key *sctp_auth_shkey_create(__u16 key_id, gfp_t gfp) } /* Free the shared key stucture */ -void sctp_auth_shkey_free(struct sctp_shared_key *sh_key) +static void sctp_auth_shkey_free(struct sctp_shared_key *sh_key) { BUG_ON(!list_empty(&sh_key->key_list)); sctp_auth_key_put(sh_key->key); @@ -220,7 +220,7 @@ static struct sctp_auth_bytes *sctp_auth_make_key_vector( /* Make a key vector based on our local parameters */ -struct sctp_auth_bytes *sctp_auth_make_local_vector( +static struct sctp_auth_bytes *sctp_auth_make_local_vector( const struct sctp_association *asoc, gfp_t gfp) { @@ -232,7 +232,7 @@ struct sctp_auth_bytes *sctp_auth_make_local_vector( } /* Make a key vector based on peer's parameters */ -struct sctp_auth_bytes *sctp_auth_make_peer_vector( +static struct sctp_auth_bytes *sctp_auth_make_peer_vector( const struct sctp_association *asoc, gfp_t gfp) { @@ -556,7 +556,7 @@ struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc) return &sctp_hmac_list[id]; } -static int __sctp_auth_find_hmacid(__u16 *hmacs, int n_elts, __u16 hmac_id) +static int __sctp_auth_find_hmacid(__be16 *hmacs, int n_elts, __be16 hmac_id) { int found = 0; int i; @@ -573,7 +573,7 @@ static int __sctp_auth_find_hmacid(__u16 *hmacs, int n_elts, __u16 hmac_id) /* See if the HMAC_ID is one that we claim as supported */ int sctp_auth_asoc_verify_hmac_id(const struct sctp_association *asoc, - __u16 hmac_id) + __be16 hmac_id) { struct sctp_hmac_algo_param *hmacs; __u16 n_elt; @@ -726,10 +726,7 @@ void sctp_auth_calculate_hmac(const struct sctp_association *asoc, /* set up scatter list */ end = skb_tail_pointer(skb); - sg_init_table(&sg, 1); - sg_set_page(&sg, virt_to_page(auth)); - sg.offset = (unsigned long)(auth) % PAGE_SIZE; - sg.length = end - (unsigned char *)auth; + sg_init_one(&sg, auth, end - (unsigned char *)auth); desc.tfm = asoc->ep->auth_hmacs[hmac_id]; desc.flags = 0; diff --git a/net/sctp/crc32c.c b/net/sctp/crc32c.c index 59cf7b06d216..181edabdb8ca 100644 --- a/net/sctp/crc32c.c +++ b/net/sctp/crc32c.c @@ -170,6 +170,7 @@ __u32 sctp_update_cksum(__u8 *buffer, __u16 length, __u32 crc32) return crc32; } +#if 0 __u32 sctp_update_copy_cksum(__u8 *to, __u8 *from, __u16 length, __u32 crc32) { __u32 i; @@ -186,6 +187,7 @@ __u32 sctp_update_copy_cksum(__u8 *to, __u8 *from, __u16 length, __u32 crc32) return crc32; } +#endif /* 0 */ __u32 sctp_end_cksum(__u32 crc32) { diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 658476c4d587..c377e4e8f653 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1513,10 +1513,7 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, struct hash_desc desc; /* Sign the message. */ - sg_init_table(&sg, 1); - sg_set_page(&sg, virt_to_page(&cookie->c)); - sg.offset = (unsigned long)(&cookie->c) % PAGE_SIZE; - sg.length = bodysize; + sg_init_one(&sg, &cookie->c, bodysize); keylen = SCTP_SECRET_SIZE; key = (char *)ep->secret_key[ep->current_key]; desc.tfm = sctp_sk(ep->base.sk)->hmac; @@ -1586,10 +1583,7 @@ struct sctp_association *sctp_unpack_cookie( /* Check the signature. */ keylen = SCTP_SECRET_SIZE; - sg_init_table(&sg, 1); - sg_set_page(&sg, virt_to_page(bear_cookie)); - sg.offset = (unsigned long)(bear_cookie) % PAGE_SIZE; - sg.length = bodysize; + sg_init_one(&sg, bear_cookie, bodysize); key = (char *)ep->secret_key[ep->current_key]; desc.tfm = sctp_sk(ep->base.sk)->hmac; desc.flags = 0; diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index b9370956b187..4be92d0a2cab 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -908,8 +908,8 @@ void sctp_ulpq_skip(struct sctp_ulpq *ulpq, __u16 sid, __u16 ssn) return; } -/* Renege 'needed' bytes from the ordering queue. */ -static __u16 sctp_ulpq_renege_order(struct sctp_ulpq *ulpq, __u16 needed) +static __u16 sctp_ulpq_renege_list(struct sctp_ulpq *ulpq, + struct sk_buff_head *list, __u16 needed) { __u16 freed = 0; __u32 tsn; @@ -919,7 +919,7 @@ static __u16 sctp_ulpq_renege_order(struct sctp_ulpq *ulpq, __u16 needed) tsnmap = &ulpq->asoc->peer.tsn_map; - while ((skb = __skb_dequeue_tail(&ulpq->lobby)) != NULL) { + while ((skb = __skb_dequeue_tail(list)) != NULL) { freed += skb_headlen(skb); event = sctp_skb2event(skb); tsn = event->tsn; @@ -933,30 +933,16 @@ static __u16 sctp_ulpq_renege_order(struct sctp_ulpq *ulpq, __u16 needed) return freed; } +/* Renege 'needed' bytes from the ordering queue. */ +static __u16 sctp_ulpq_renege_order(struct sctp_ulpq *ulpq, __u16 needed) +{ + return sctp_ulpq_renege_list(ulpq, &ulpq->lobby, needed); +} + /* Renege 'needed' bytes from the reassembly queue. */ static __u16 sctp_ulpq_renege_frags(struct sctp_ulpq *ulpq, __u16 needed) { - __u16 freed = 0; - __u32 tsn; - struct sk_buff *skb; - struct sctp_ulpevent *event; - struct sctp_tsnmap *tsnmap; - - tsnmap = &ulpq->asoc->peer.tsn_map; - - /* Walk backwards through the list, reneges the newest tsns. */ - while ((skb = __skb_dequeue_tail(&ulpq->reasm)) != NULL) { - freed += skb_headlen(skb); - event = sctp_skb2event(skb); - tsn = event->tsn; - - sctp_ulpevent_free(event); - sctp_tsnmap_renege(tsnmap, tsn); - if (freed >= needed) - return freed; - } - - return freed; + return sctp_ulpq_renege_list(ulpq, &ulpq->reasm, needed); } /* Partial deliver the first message as there is pressure on rwnd. */ diff --git a/net/socket.c b/net/socket.c index 540013ea8620..5d879fd3d01d 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1250,11 +1250,14 @@ asmlinkage long sys_socketpair(int family, int type, int protocol, goto out_release_both; fd1 = sock_alloc_fd(&newfile1); - if (unlikely(fd1 < 0)) + if (unlikely(fd1 < 0)) { + err = fd1; goto out_release_both; + } fd2 = sock_alloc_fd(&newfile2); if (unlikely(fd2 < 0)) { + err = fd2; put_filp(newfile1); put_unused_fd(fd1); goto out_release_both; diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 32be431affcf..91cd8f0d1e10 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -75,7 +75,7 @@ krb5_encrypt( memcpy(local_iv, iv, crypto_blkcipher_ivsize(tfm)); memcpy(out, in, length); - sg_set_buf(sg, out, length); + sg_init_one(sg, out, length); ret = crypto_blkcipher_encrypt_iv(&desc, sg, sg, length); out: @@ -110,7 +110,7 @@ krb5_decrypt( memcpy(local_iv,iv, crypto_blkcipher_ivsize(tfm)); memcpy(out, in, length); - sg_set_buf(sg, out, length); + sg_init_one(sg, out, length); ret = crypto_blkcipher_decrypt_iv(&desc, sg, sg, length); out: @@ -146,7 +146,7 @@ make_checksum(char *cksumname, char *header, int hdrlen, struct xdr_buf *body, err = crypto_hash_init(&desc); if (err) goto out; - sg_set_buf(sg, header, hdrlen); + sg_init_one(sg, header, hdrlen); err = crypto_hash_update(&desc, sg, hdrlen); if (err) goto out; @@ -188,8 +188,6 @@ encryptor(struct scatterlist *sg, void *data) /* Worst case is 4 fragments: head, end of page 1, start * of page 2, tail. Anything more is a bug. */ BUG_ON(desc->fragno > 3); - desc->infrags[desc->fragno] = *sg; - desc->outfrags[desc->fragno] = *sg; page_pos = desc->pos - outbuf->head[0].iov_len; if (page_pos >= 0 && page_pos < outbuf->page_len) { @@ -199,7 +197,10 @@ encryptor(struct scatterlist *sg, void *data) } else { in_page = sg_page(sg); } - sg_set_page(&desc->infrags[desc->fragno], in_page); + sg_set_page(&desc->infrags[desc->fragno], in_page, sg->length, + sg->offset); + sg_set_page(&desc->outfrags[desc->fragno], sg_page(sg), sg->length, + sg->offset); desc->fragno++; desc->fraglen += sg->length; desc->pos += sg->length; @@ -210,16 +211,22 @@ encryptor(struct scatterlist *sg, void *data) if (thislen == 0) return 0; + sg_mark_end(desc->infrags, desc->fragno); + sg_mark_end(desc->outfrags, desc->fragno); + ret = crypto_blkcipher_encrypt_iv(&desc->desc, desc->outfrags, desc->infrags, thislen); if (ret) return ret; + + sg_init_table(desc->infrags, 4); + sg_init_table(desc->outfrags, 4); + if (fraglen) { - sg_set_page(&desc->outfrags[0], sg_page(sg)); - desc->outfrags[0].offset = sg->offset + sg->length - fraglen; - desc->outfrags[0].length = fraglen; + sg_set_page(&desc->outfrags[0], sg_page(sg), fraglen, + sg->offset + sg->length - fraglen); desc->infrags[0] = desc->outfrags[0]; - sg_set_page(&desc->infrags[0], in_page); + sg_assign_page(&desc->infrags[0], in_page); desc->fragno = 1; desc->fraglen = fraglen; } else { @@ -248,6 +255,9 @@ gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf, desc.fragno = 0; desc.fraglen = 0; + sg_init_table(desc.infrags, 4); + sg_init_table(desc.outfrags, 4); + ret = xdr_process_buf(buf, offset, buf->len - offset, encryptor, &desc); return ret; } @@ -272,7 +282,8 @@ decryptor(struct scatterlist *sg, void *data) /* Worst case is 4 fragments: head, end of page 1, start * of page 2, tail. Anything more is a bug. */ BUG_ON(desc->fragno > 3); - desc->frags[desc->fragno] = *sg; + sg_set_page(&desc->frags[desc->fragno], sg_page(sg), sg->length, + sg->offset); desc->fragno++; desc->fraglen += sg->length; @@ -282,14 +293,18 @@ decryptor(struct scatterlist *sg, void *data) if (thislen == 0) return 0; + sg_mark_end(desc->frags, desc->fragno); + ret = crypto_blkcipher_decrypt_iv(&desc->desc, desc->frags, desc->frags, thislen); if (ret) return ret; + + sg_init_table(desc->frags, 4); + if (fraglen) { - sg_set_page(&desc->frags[0], sg_page(sg)); - desc->frags[0].offset = sg->offset + sg->length - fraglen; - desc->frags[0].length = fraglen; + sg_set_page(&desc->frags[0], sg_page(sg), fraglen, + sg->offset + sg->length - fraglen); desc->fragno = 1; desc->fraglen = fraglen; } else { @@ -314,6 +329,9 @@ gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf, desc.desc.flags = 0; desc.fragno = 0; desc.fraglen = 0; + + sg_init_table(desc.frags, 4); + return xdr_process_buf(buf, offset, buf->len - offset, decryptor, &desc); } diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c index d158635de6c0..abf17ce2e3b1 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_seal.c +++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c @@ -173,7 +173,7 @@ make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header, if (err) goto out; - sg_set_buf(sg, header, hdrlen); + sg_init_one(sg, header, hdrlen); crypto_hash_update(&desc, sg, sg->length); xdr_process_buf(body, body_offset, body->len - body_offset, diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c index 864b541bbf51..2be714e9b382 100644 --- a/net/sunrpc/sysctl.c +++ b/net/sunrpc/sysctl.c @@ -87,9 +87,8 @@ proc_dodebug(ctl_table *table, int write, struct file *file, left--, s++; *(unsigned int *) table->data = value; /* Display the RPC tasks on writing to rpc_debug */ - if (table->ctl_name == CTL_RPCDEBUG) { + if (strcmp(table->procname, "rpc_debug") == 0) rpc_show_tasks(); - } } else { if (!access_ok(VERIFY_WRITE, buffer, left)) return -EFAULT; diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 3d1f7cdf9dd0..fdc5e6d7562b 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -1030,6 +1030,8 @@ xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, unsigned page_len, thislen, page_offset; struct scatterlist sg[1]; + sg_init_table(sg, 1); + if (offset >= buf->head[0].iov_len) { offset -= buf->head[0].iov_len; } else { @@ -1059,9 +1061,7 @@ xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, do { if (thislen > page_len) thislen = page_len; - sg_set_page(sg, buf->pages[i]); - sg->offset = page_offset; - sg->length = thislen; + sg_set_page(sg, buf->pages[i], thislen, page_offset); ret = actor(sg, data); if (ret) goto out; diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 12db63580427..9e11ce715958 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c @@ -181,7 +181,7 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, struct rpcrdma_read_chunk *cur_rchunk = NULL; struct rpcrdma_write_array *warray = NULL; struct rpcrdma_write_chunk *cur_wchunk = NULL; - u32 *iptr = headerp->rm_body.rm_chunks; + __be32 *iptr = headerp->rm_body.rm_chunks; if (type == rpcrdma_readch || type == rpcrdma_areadch) { /* a read chunk - server will RDMA Read our memory */ @@ -217,25 +217,25 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, cur_rchunk->rc_target.rs_handle = htonl(seg->mr_rkey); cur_rchunk->rc_target.rs_length = htonl(seg->mr_len); xdr_encode_hyper( - (u32 *)&cur_rchunk->rc_target.rs_offset, + (__be32 *)&cur_rchunk->rc_target.rs_offset, seg->mr_base); dprintk("RPC: %s: read chunk " "elem %d@0x%llx:0x%x pos %d (%s)\n", __func__, - seg->mr_len, seg->mr_base, seg->mr_rkey, pos, - n < nsegs ? "more" : "last"); + seg->mr_len, (unsigned long long)seg->mr_base, + seg->mr_rkey, pos, n < nsegs ? "more" : "last"); cur_rchunk++; r_xprt->rx_stats.read_chunk_count++; } else { /* write/reply */ cur_wchunk->wc_target.rs_handle = htonl(seg->mr_rkey); cur_wchunk->wc_target.rs_length = htonl(seg->mr_len); xdr_encode_hyper( - (u32 *)&cur_wchunk->wc_target.rs_offset, + (__be32 *)&cur_wchunk->wc_target.rs_offset, seg->mr_base); dprintk("RPC: %s: %s chunk " "elem %d@0x%llx:0x%x (%s)\n", __func__, (type == rpcrdma_replych) ? "reply" : "write", - seg->mr_len, seg->mr_base, seg->mr_rkey, - n < nsegs ? "more" : "last"); + seg->mr_len, (unsigned long long)seg->mr_base, + seg->mr_rkey, n < nsegs ? "more" : "last"); cur_wchunk++; if (type == rpcrdma_replych) r_xprt->rx_stats.reply_chunk_count++; @@ -257,14 +257,14 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, * finish off header. If write, marshal discrim and nchunks. */ if (cur_rchunk) { - iptr = (u32 *) cur_rchunk; + iptr = (__be32 *) cur_rchunk; *iptr++ = xdr_zero; /* finish the read chunk list */ *iptr++ = xdr_zero; /* encode a NULL write chunk list */ *iptr++ = xdr_zero; /* encode a NULL reply chunk */ } else { warray->wc_discrim = xdr_one; warray->wc_nchunks = htonl(nchunks); - iptr = (u32 *) cur_wchunk; + iptr = (__be32 *) cur_wchunk; if (type == rpcrdma_writech) { *iptr++ = xdr_zero; /* finish the write chunk list */ *iptr++ = xdr_zero; /* encode a NULL reply chunk */ @@ -559,7 +559,7 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst) * RDMA'd by server. See map at rpcrdma_create_chunks()! :-) */ static int -rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp) +rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, __be32 **iptrp) { unsigned int i, total_len; struct rpcrdma_write_chunk *cur_wchunk; @@ -573,11 +573,11 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp) struct rpcrdma_segment *seg = &cur_wchunk->wc_target; ifdebug(FACILITY) { u64 off; - xdr_decode_hyper((u32 *)&seg->rs_offset, &off); + xdr_decode_hyper((__be32 *)&seg->rs_offset, &off); dprintk("RPC: %s: chunk %d@0x%llx:0x%x\n", __func__, ntohl(seg->rs_length), - off, + (unsigned long long)off, ntohl(seg->rs_handle)); } total_len += ntohl(seg->rs_length); @@ -585,7 +585,7 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp) } /* check and adjust for properly terminated write chunk */ if (wrchunk) { - u32 *w = (u32 *) cur_wchunk; + __be32 *w = (__be32 *) cur_wchunk; if (*w++ != xdr_zero) return -1; cur_wchunk = (struct rpcrdma_write_chunk *) w; @@ -593,7 +593,7 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, u32 **iptrp) if ((char *) cur_wchunk > rep->rr_base + rep->rr_len) return -1; - *iptrp = (u32 *) cur_wchunk; + *iptrp = (__be32 *) cur_wchunk; return total_len; } @@ -721,7 +721,7 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep) struct rpc_rqst *rqst; struct rpc_xprt *xprt = rep->rr_xprt; struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); - u32 *iptr; + __be32 *iptr; int i, rdmalen, status; /* Check status. If bad, signal disconnect and return rep to pool */ @@ -801,7 +801,7 @@ repost: r_xprt->rx_stats.total_rdma_reply += rdmalen; } else { /* else ordinary inline */ - iptr = (u32 *)((unsigned char *)headerp + 28); + iptr = (__be32 *)((unsigned char *)headerp + 28); rep->rr_len -= 28; /*sizeof *headerp;*/ status = rep->rr_len; } @@ -816,7 +816,7 @@ repost: headerp->rm_body.rm_chunks[2] != xdr_one || req->rl_nchunks == 0) goto badheader; - iptr = (u32 *)((unsigned char *)headerp + 28); + iptr = (__be32 *)((unsigned char *)headerp + 28); rdmalen = rpcrdma_count_chunks(rep, req->rl_nchunks, 0, &iptr); if (rdmalen < 0) goto badheader; diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index 313d4bed3aa9..0426388d351d 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c @@ -553,9 +553,7 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, if (copy > len) copy = len; - sg_set_page(&sg, virt_to_page(skb->data + offset)); - sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; - sg.length = copy; + sg_init_one(&sg, skb->data + offset, copy); err = icv_update(desc, &sg, copy); if (unlikely(err)) @@ -578,9 +576,9 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, if (copy > len) copy = len; - sg_set_page(&sg, frag->page); - sg.offset = frag->page_offset + offset-start; - sg.length = copy; + sg_init_table(&sg, 1); + sg_set_page(&sg, frag->page, copy, + frag->page_offset + offset-start); err = icv_update(desc, &sg, copy); if (unlikely(err)) |