diff options
Diffstat (limited to '3.12.4/1003_linux-3.12.4.patch')
-rw-r--r-- | 3.12.4/1003_linux-3.12.4.patch | 4725 |
1 files changed, 4725 insertions, 0 deletions
diff --git a/3.12.4/1003_linux-3.12.4.patch b/3.12.4/1003_linux-3.12.4.patch new file mode 100644 index 0000000..819cfed --- /dev/null +++ b/3.12.4/1003_linux-3.12.4.patch @@ -0,0 +1,4725 @@ +diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt +index a46d785..7d8dc93 100644 +--- a/Documentation/networking/ip-sysctl.txt ++++ b/Documentation/networking/ip-sysctl.txt +@@ -588,9 +588,6 @@ tcp_limit_output_bytes - INTEGER + typical pfifo_fast qdiscs. + tcp_limit_output_bytes limits the number of bytes on qdisc + or device to reduce artificial RTT/cwnd and reduce bufferbloat. +- Note: For GSO/TSO enabled flows, we try to have at least two +- packets in flight. Reducing tcp_limit_output_bytes might also +- reduce the size of individual GSO packet (64KB being the max) + Default: 131072 + + tcp_challenge_ack_limit - INTEGER +diff --git a/Makefile b/Makefile +index b28bc57..3b7165e 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 12 +-SUBLEVEL = 3 ++SUBLEVEL = 4 + EXTRAVERSION = + NAME = One Giant Leap for Frogkind + +diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c +index 516593e..26328e8 100644 +--- a/arch/x86/net/bpf_jit_comp.c ++++ b/arch/x86/net/bpf_jit_comp.c +@@ -788,5 +788,7 @@ void bpf_jit_free(struct sk_filter *fp) + if (fp->bpf_func != sk_run_filter) { + INIT_WORK(&fp->work, bpf_jit_free_deferred); + schedule_work(&fp->work); ++ } else { ++ kfree(fp); + } + } +diff --git a/block/blk-core.c b/block/blk-core.c +index 0c611d8..fce4b93 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -741,9 +741,17 @@ blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn, + + q->sg_reserved_size = INT_MAX; + ++ /* Protect q->elevator from elevator_change */ ++ mutex_lock(&q->sysfs_lock); ++ + /* init elevator */ +- if (elevator_init(q, NULL)) ++ if (elevator_init(q, NULL)) { ++ mutex_unlock(&q->sysfs_lock); + return NULL; ++ } ++ ++ mutex_unlock(&q->sysfs_lock); ++ + return q; + } + EXPORT_SYMBOL(blk_init_allocated_queue); +diff --git a/block/elevator.c b/block/elevator.c +index 2bcbd8c..b7ff286 100644 +--- a/block/elevator.c ++++ b/block/elevator.c +@@ -186,6 +186,12 @@ int elevator_init(struct request_queue *q, char *name) + struct elevator_type *e = NULL; + int err; + ++ /* ++ * q->sysfs_lock must be held to provide mutual exclusion between ++ * elevator_switch() and here. ++ */ ++ lockdep_assert_held(&q->sysfs_lock); ++ + if (unlikely(q->elevator)) + return 0; + +@@ -959,7 +965,7 @@ fail_init: + /* + * Switch this queue to the given IO scheduler. + */ +-int elevator_change(struct request_queue *q, const char *name) ++static int __elevator_change(struct request_queue *q, const char *name) + { + char elevator_name[ELV_NAME_MAX]; + struct elevator_type *e; +@@ -981,6 +987,18 @@ int elevator_change(struct request_queue *q, const char *name) + + return elevator_switch(q, e); + } ++ ++int elevator_change(struct request_queue *q, const char *name) ++{ ++ int ret; ++ ++ /* Protect q->elevator from elevator_init() */ ++ mutex_lock(&q->sysfs_lock); ++ ret = __elevator_change(q, name); ++ mutex_unlock(&q->sysfs_lock); ++ ++ return ret; ++} + EXPORT_SYMBOL(elevator_change); + + ssize_t elv_iosched_store(struct request_queue *q, const char *name, +@@ -991,7 +1009,7 @@ ssize_t elv_iosched_store(struct request_queue *q, const char *name, + if (!q->elevator) + return count; + +- ret = elevator_change(q, name); ++ ret = __elevator_change(q, name); + if (!ret) + return count; + +diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c +index 0262210..8502462 100644 +--- a/crypto/algif_hash.c ++++ b/crypto/algif_hash.c +@@ -114,6 +114,9 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page, + struct hash_ctx *ctx = ask->private; + int err; + ++ if (flags & MSG_SENDPAGE_NOTLAST) ++ flags |= MSG_MORE; ++ + lock_sock(sk); + sg_init_table(ctx->sgl.sg, 1); + sg_set_page(ctx->sgl.sg, page, size, offset); +@@ -161,8 +164,6 @@ static int hash_recvmsg(struct kiocb *unused, struct socket *sock, + else if (len < ds) + msg->msg_flags |= MSG_TRUNC; + +- msg->msg_namelen = 0; +- + lock_sock(sk); + if (ctx->more) { + ctx->more = 0; +diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c +index a1c4f0a..a19c027 100644 +--- a/crypto/algif_skcipher.c ++++ b/crypto/algif_skcipher.c +@@ -378,6 +378,9 @@ static ssize_t skcipher_sendpage(struct socket *sock, struct page *page, + struct skcipher_sg_list *sgl; + int err = -EINVAL; + ++ if (flags & MSG_SENDPAGE_NOTLAST) ++ flags |= MSG_MORE; ++ + lock_sock(sk); + if (!ctx->more && ctx->used) + goto unlock; +@@ -432,7 +435,6 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock, + long copied = 0; + + lock_sock(sk); +- msg->msg_namelen = 0; + for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0; + iovlen--, iov++) { + unsigned long seglen = iov->iov_len; +diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c +index 272f009..1bdf104 100644 +--- a/drivers/atm/idt77252.c ++++ b/drivers/atm/idt77252.c +@@ -3511,7 +3511,7 @@ static int init_card(struct atm_dev *dev) + tmp = dev_get_by_name(&init_net, tname); /* jhs: was "tmp = dev_get(tname);" */ + if (tmp) { + memcpy(card->atmdev->esi, tmp->dev_addr, 6); +- ++ dev_put(tmp); + printk("%s: ESI %pM\n", card->name, card->atmdev->esi); + } + /* +diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c +index c73fc2b..18c5b9b 100644 +--- a/drivers/connector/cn_proc.c ++++ b/drivers/connector/cn_proc.c +@@ -32,11 +32,23 @@ + #include <linux/atomic.h> + #include <linux/pid_namespace.h> + +-#include <asm/unaligned.h> +- + #include <linux/cn_proc.h> + +-#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event)) ++/* ++ * Size of a cn_msg followed by a proc_event structure. Since the ++ * sizeof struct cn_msg is a multiple of 4 bytes, but not 8 bytes, we ++ * add one 4-byte word to the size here, and then start the actual ++ * cn_msg structure 4 bytes into the stack buffer. The result is that ++ * the immediately following proc_event structure is aligned to 8 bytes. ++ */ ++#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event) + 4) ++ ++/* See comment above; we test our assumption about sizeof struct cn_msg here. */ ++static inline struct cn_msg *buffer_to_cn_msg(__u8 *buffer) ++{ ++ BUILD_BUG_ON(sizeof(struct cn_msg) != 20); ++ return (struct cn_msg *)(buffer + 4); ++} + + static atomic_t proc_event_num_listeners = ATOMIC_INIT(0); + static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC }; +@@ -56,19 +68,19 @@ void proc_fork_connector(struct task_struct *task) + { + struct cn_msg *msg; + struct proc_event *ev; +- __u8 buffer[CN_PROC_MSG_SIZE]; ++ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); + struct timespec ts; + struct task_struct *parent; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + +- msg = (struct cn_msg *)buffer; ++ msg = buffer_to_cn_msg(buffer); + ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); + get_seq(&msg->seq, &ev->cpu); + ktime_get_ts(&ts); /* get high res monotonic timestamp */ +- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); ++ ev->timestamp_ns = timespec_to_ns(&ts); + ev->what = PROC_EVENT_FORK; + rcu_read_lock(); + parent = rcu_dereference(task->real_parent); +@@ -91,17 +103,17 @@ void proc_exec_connector(struct task_struct *task) + struct cn_msg *msg; + struct proc_event *ev; + struct timespec ts; +- __u8 buffer[CN_PROC_MSG_SIZE]; ++ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + +- msg = (struct cn_msg *)buffer; ++ msg = buffer_to_cn_msg(buffer); + ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); + get_seq(&msg->seq, &ev->cpu); + ktime_get_ts(&ts); /* get high res monotonic timestamp */ +- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); ++ ev->timestamp_ns = timespec_to_ns(&ts); + ev->what = PROC_EVENT_EXEC; + ev->event_data.exec.process_pid = task->pid; + ev->event_data.exec.process_tgid = task->tgid; +@@ -117,14 +129,14 @@ void proc_id_connector(struct task_struct *task, int which_id) + { + struct cn_msg *msg; + struct proc_event *ev; +- __u8 buffer[CN_PROC_MSG_SIZE]; ++ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); + struct timespec ts; + const struct cred *cred; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + +- msg = (struct cn_msg *)buffer; ++ msg = buffer_to_cn_msg(buffer); + ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); + ev->what = which_id; +@@ -145,7 +157,7 @@ void proc_id_connector(struct task_struct *task, int which_id) + rcu_read_unlock(); + get_seq(&msg->seq, &ev->cpu); + ktime_get_ts(&ts); /* get high res monotonic timestamp */ +- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); ++ ev->timestamp_ns = timespec_to_ns(&ts); + + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ +@@ -159,17 +171,17 @@ void proc_sid_connector(struct task_struct *task) + struct cn_msg *msg; + struct proc_event *ev; + struct timespec ts; +- __u8 buffer[CN_PROC_MSG_SIZE]; ++ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + +- msg = (struct cn_msg *)buffer; ++ msg = buffer_to_cn_msg(buffer); + ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); + get_seq(&msg->seq, &ev->cpu); + ktime_get_ts(&ts); /* get high res monotonic timestamp */ +- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); ++ ev->timestamp_ns = timespec_to_ns(&ts); + ev->what = PROC_EVENT_SID; + ev->event_data.sid.process_pid = task->pid; + ev->event_data.sid.process_tgid = task->tgid; +@@ -186,17 +198,17 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id) + struct cn_msg *msg; + struct proc_event *ev; + struct timespec ts; +- __u8 buffer[CN_PROC_MSG_SIZE]; ++ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + +- msg = (struct cn_msg *)buffer; ++ msg = buffer_to_cn_msg(buffer); + ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); + get_seq(&msg->seq, &ev->cpu); + ktime_get_ts(&ts); /* get high res monotonic timestamp */ +- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); ++ ev->timestamp_ns = timespec_to_ns(&ts); + ev->what = PROC_EVENT_PTRACE; + ev->event_data.ptrace.process_pid = task->pid; + ev->event_data.ptrace.process_tgid = task->tgid; +@@ -221,17 +233,17 @@ void proc_comm_connector(struct task_struct *task) + struct cn_msg *msg; + struct proc_event *ev; + struct timespec ts; +- __u8 buffer[CN_PROC_MSG_SIZE]; ++ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + +- msg = (struct cn_msg *)buffer; ++ msg = buffer_to_cn_msg(buffer); + ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); + get_seq(&msg->seq, &ev->cpu); + ktime_get_ts(&ts); /* get high res monotonic timestamp */ +- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); ++ ev->timestamp_ns = timespec_to_ns(&ts); + ev->what = PROC_EVENT_COMM; + ev->event_data.comm.process_pid = task->pid; + ev->event_data.comm.process_tgid = task->tgid; +@@ -248,18 +260,18 @@ void proc_coredump_connector(struct task_struct *task) + { + struct cn_msg *msg; + struct proc_event *ev; +- __u8 buffer[CN_PROC_MSG_SIZE]; ++ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); + struct timespec ts; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + +- msg = (struct cn_msg *)buffer; ++ msg = buffer_to_cn_msg(buffer); + ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); + get_seq(&msg->seq, &ev->cpu); + ktime_get_ts(&ts); /* get high res monotonic timestamp */ +- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); ++ ev->timestamp_ns = timespec_to_ns(&ts); + ev->what = PROC_EVENT_COREDUMP; + ev->event_data.coredump.process_pid = task->pid; + ev->event_data.coredump.process_tgid = task->tgid; +@@ -275,18 +287,18 @@ void proc_exit_connector(struct task_struct *task) + { + struct cn_msg *msg; + struct proc_event *ev; +- __u8 buffer[CN_PROC_MSG_SIZE]; ++ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); + struct timespec ts; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + +- msg = (struct cn_msg *)buffer; ++ msg = buffer_to_cn_msg(buffer); + ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); + get_seq(&msg->seq, &ev->cpu); + ktime_get_ts(&ts); /* get high res monotonic timestamp */ +- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); ++ ev->timestamp_ns = timespec_to_ns(&ts); + ev->what = PROC_EVENT_EXIT; + ev->event_data.exit.process_pid = task->pid; + ev->event_data.exit.process_tgid = task->tgid; +@@ -312,18 +324,18 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) + { + struct cn_msg *msg; + struct proc_event *ev; +- __u8 buffer[CN_PROC_MSG_SIZE]; ++ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); + struct timespec ts; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + +- msg = (struct cn_msg *)buffer; ++ msg = buffer_to_cn_msg(buffer); + ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); + msg->seq = rcvd_seq; + ktime_get_ts(&ts); /* get high res monotonic timestamp */ +- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); ++ ev->timestamp_ns = timespec_to_ns(&ts); + ev->cpu = -1; + ev->what = PROC_EVENT_NONE; + ev->event_data.ack.err = err; +diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c +index 06022e3..615c5b2 100644 +--- a/drivers/gpu/drm/radeon/r600_hdmi.c ++++ b/drivers/gpu/drm/radeon/r600_hdmi.c +@@ -24,6 +24,7 @@ + * Authors: Christian König + */ + #include <linux/hdmi.h> ++#include <linux/gcd.h> + #include <drm/drmP.h> + #include <drm/radeon_drm.h> + #include "radeon.h" +@@ -57,35 +58,57 @@ enum r600_hdmi_iec_status_bits { + static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { + /* 32kHz 44.1kHz 48kHz */ + /* Clock N CTS N CTS N CTS */ +- { 25175, 4576, 28125, 7007, 31250, 6864, 28125 }, /* 25,20/1.001 MHz */ ++ { 25175, 4096, 25175, 28224, 125875, 6144, 25175 }, /* 25,20/1.001 MHz */ + { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */ + { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */ + { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */ + { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */ + { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */ +- { 74176, 11648, 210937, 17836, 234375, 11648, 140625 }, /* 74.25/1.001 MHz */ ++ { 74176, 4096, 74176, 5733, 75335, 6144, 74176 }, /* 74.25/1.001 MHz */ + { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ +- { 148352, 11648, 421875, 8918, 234375, 5824, 140625 }, /* 148.50/1.001 MHz */ ++ { 148352, 4096, 148352, 5733, 150670, 6144, 148352 }, /* 148.50/1.001 MHz */ + { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ +- { 0, 4096, 0, 6272, 0, 6144, 0 } /* Other */ + }; + ++ + /* +- * calculate CTS value if it's not found in the table ++ * calculate CTS and N values if they are not found in the table + */ +-static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int N, int freq) ++static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int *N, int freq) + { +- u64 n; +- u32 d; +- +- if (*CTS == 0) { +- n = (u64)clock * (u64)N * 1000ULL; +- d = 128 * freq; +- do_div(n, d); +- *CTS = n; +- } +- DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n", +- N, *CTS, freq); ++ int n, cts; ++ unsigned long div, mul; ++ ++ /* Safe, but overly large values */ ++ n = 128 * freq; ++ cts = clock * 1000; ++ ++ /* Smallest valid fraction */ ++ div = gcd(n, cts); ++ ++ n /= div; ++ cts /= div; ++ ++ /* ++ * The optimal N is 128*freq/1000. Calculate the closest larger ++ * value that doesn't truncate any bits. ++ */ ++ mul = ((128*freq/1000) + (n-1))/n; ++ ++ n *= mul; ++ cts *= mul; ++ ++ /* Check that we are in spec (not always possible) */ ++ if (n < (128*freq/1500)) ++ printk(KERN_WARNING "Calculated ACR N value is too small. You may experience audio problems.\n"); ++ if (n > (128*freq/300)) ++ printk(KERN_WARNING "Calculated ACR N value is too large. You may experience audio problems.\n"); ++ ++ *N = n; ++ *CTS = cts; ++ ++ DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n", ++ *N, *CTS, freq); + } + + struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock) +@@ -93,15 +116,16 @@ struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock) + struct radeon_hdmi_acr res; + u8 i; + +- for (i = 0; r600_hdmi_predefined_acr[i].clock != clock && +- r600_hdmi_predefined_acr[i].clock != 0; i++) +- ; +- res = r600_hdmi_predefined_acr[i]; ++ /* Precalculated values for common clocks */ ++ for (i = 0; i < ARRAY_SIZE(r600_hdmi_predefined_acr); i++) { ++ if (r600_hdmi_predefined_acr[i].clock == clock) ++ return r600_hdmi_predefined_acr[i]; ++ } + +- /* In case some CTS are missing */ +- r600_hdmi_calc_cts(clock, &res.cts_32khz, res.n_32khz, 32000); +- r600_hdmi_calc_cts(clock, &res.cts_44_1khz, res.n_44_1khz, 44100); +- r600_hdmi_calc_cts(clock, &res.cts_48khz, res.n_48khz, 48000); ++ /* And odd clocks get manually calculated */ ++ r600_hdmi_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000); ++ r600_hdmi_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100); ++ r600_hdmi_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000); + + return res; + } +diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c +index f042a6c..55e4920 100644 +--- a/drivers/hid/hid-elo.c ++++ b/drivers/hid/hid-elo.c +@@ -181,7 +181,40 @@ fail: + */ + static bool elo_broken_firmware(struct usb_device *dev) + { +- return use_fw_quirk && le16_to_cpu(dev->descriptor.bcdDevice) == 0x10d; ++ struct usb_device *hub = dev->parent; ++ struct usb_device *child = NULL; ++ u16 fw_lvl = le16_to_cpu(dev->descriptor.bcdDevice); ++ u16 child_vid, child_pid; ++ int i; ++ ++ if (!use_fw_quirk) ++ return false; ++ if (fw_lvl != 0x10d) ++ return false; ++ ++ /* iterate sibling devices of the touch controller */ ++ usb_hub_for_each_child(hub, i, child) { ++ child_vid = le16_to_cpu(child->descriptor.idVendor); ++ child_pid = le16_to_cpu(child->descriptor.idProduct); ++ ++ /* ++ * If one of the devices below is present attached as a sibling of ++ * the touch controller then this is a newer IBM 4820 monitor that ++ * does not need the IBM-requested workaround if fw level is ++ * 0x010d - aka 'M'. ++ * No other HW can have this combination. ++ */ ++ if (child_vid==0x04b3) { ++ switch (child_pid) { ++ case 0x4676: /* 4820 21x Video */ ++ case 0x4677: /* 4820 51x Video */ ++ case 0x4678: /* 4820 2Lx Video */ ++ case 0x4679: /* 4820 5Lx Video */ ++ return false; ++ } ++ } ++ } ++ return true; + } + + static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id) +diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c +index 1bfd292..06eb45f 100644 +--- a/drivers/hid/hid-lg.c ++++ b/drivers/hid/hid-lg.c +@@ -47,6 +47,7 @@ + #define DFP_RDESC_ORIG_SIZE 97 + #define FV_RDESC_ORIG_SIZE 130 + #define MOMO_RDESC_ORIG_SIZE 87 ++#define MOMO2_RDESC_ORIG_SIZE 87 + + /* Fixed report descriptors for Logitech Driving Force (and Pro) + * wheel controllers +@@ -284,6 +285,54 @@ static __u8 momo_rdesc_fixed[] = { + 0xC0 /* End Collection */ + }; + ++static __u8 momo2_rdesc_fixed[] = { ++0x05, 0x01, /* Usage Page (Desktop), */ ++0x09, 0x04, /* Usage (Joystik), */ ++0xA1, 0x01, /* Collection (Application), */ ++0xA1, 0x02, /* Collection (Logical), */ ++0x95, 0x01, /* Report Count (1), */ ++0x75, 0x0A, /* Report Size (10), */ ++0x15, 0x00, /* Logical Minimum (0), */ ++0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ ++0x35, 0x00, /* Physical Minimum (0), */ ++0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ ++0x09, 0x30, /* Usage (X), */ ++0x81, 0x02, /* Input (Variable), */ ++0x95, 0x0A, /* Report Count (10), */ ++0x75, 0x01, /* Report Size (1), */ ++0x25, 0x01, /* Logical Maximum (1), */ ++0x45, 0x01, /* Physical Maximum (1), */ ++0x05, 0x09, /* Usage Page (Button), */ ++0x19, 0x01, /* Usage Minimum (01h), */ ++0x29, 0x0A, /* Usage Maximum (0Ah), */ ++0x81, 0x02, /* Input (Variable), */ ++0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ ++0x09, 0x00, /* Usage (00h), */ ++0x95, 0x04, /* Report Count (4), */ ++0x81, 0x02, /* Input (Variable), */ ++0x95, 0x01, /* Report Count (1), */ ++0x75, 0x08, /* Report Size (8), */ ++0x26, 0xFF, 0x00, /* Logical Maximum (255), */ ++0x46, 0xFF, 0x00, /* Physical Maximum (255), */ ++0x09, 0x01, /* Usage (01h), */ ++0x81, 0x02, /* Input (Variable), */ ++0x05, 0x01, /* Usage Page (Desktop), */ ++0x09, 0x31, /* Usage (Y), */ ++0x81, 0x02, /* Input (Variable), */ ++0x09, 0x32, /* Usage (Z), */ ++0x81, 0x02, /* Input (Variable), */ ++0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ ++0x09, 0x00, /* Usage (00h), */ ++0x81, 0x02, /* Input (Variable), */ ++0xC0, /* End Collection, */ ++0xA1, 0x02, /* Collection (Logical), */ ++0x09, 0x02, /* Usage (02h), */ ++0x95, 0x07, /* Report Count (7), */ ++0x91, 0x02, /* Output (Variable), */ ++0xC0, /* End Collection, */ ++0xC0 /* End Collection */ ++}; ++ + /* + * Certain Logitech keyboards send in report #3 keys which are far + * above the logical maximum described in descriptor. This extends +@@ -343,6 +392,15 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, + } + break; + ++ case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2: ++ if (*rsize == MOMO2_RDESC_ORIG_SIZE) { ++ hid_info(hdev, ++ "fixing up Logitech Momo Racing Force (Black) report descriptor\n"); ++ rdesc = momo2_rdesc_fixed; ++ *rsize = sizeof(momo2_rdesc_fixed); ++ } ++ break; ++ + case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL: + if (*rsize == FV_RDESC_ORIG_SIZE) { + hid_info(hdev, +diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c +index 15e9b57..40203ad 100644 +--- a/drivers/iommu/intel-iommu.c ++++ b/drivers/iommu/intel-iommu.c +@@ -782,7 +782,11 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, + int offset; + + BUG_ON(!domain->pgd); +- BUG_ON(addr_width < BITS_PER_LONG && pfn >> addr_width); ++ ++ if (addr_width < BITS_PER_LONG && pfn >> addr_width) ++ /* Address beyond IOMMU's addressing capabilities. */ ++ return NULL; ++ + parent = domain->pgd; + + while (level > 0) { +diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c +index f71673d..b97d70b 100644 +--- a/drivers/iommu/intel_irq_remapping.c ++++ b/drivers/iommu/intel_irq_remapping.c +@@ -525,12 +525,13 @@ static int __init intel_irq_remapping_supported(void) + if (disable_irq_remap) + return 0; + if (irq_remap_broken) { +- WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND, +- "This system BIOS has enabled interrupt remapping\n" +- "on a chipset that contains an erratum making that\n" +- "feature unstable. To maintain system stability\n" +- "interrupt remapping is being disabled. Please\n" +- "contact your BIOS vendor for an update\n"); ++ printk(KERN_WARNING ++ "This system BIOS has enabled interrupt remapping\n" ++ "on a chipset that contains an erratum making that\n" ++ "feature unstable. To maintain system stability\n" ++ "interrupt remapping is being disabled. Please\n" ++ "contact your BIOS vendor for an update\n"); ++ add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); + disable_irq_remap = 1; + return 0; + } +diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c +index baf2686..02125e6 100644 +--- a/drivers/isdn/isdnloop/isdnloop.c ++++ b/drivers/isdn/isdnloop/isdnloop.c +@@ -1083,8 +1083,10 @@ isdnloop_start(isdnloop_card *card, isdnloop_sdef *sdefp) + spin_unlock_irqrestore(&card->isdnloop_lock, flags); + return -ENOMEM; + } +- for (i = 0; i < 3; i++) +- strcpy(card->s0num[i], sdef.num[i]); ++ for (i = 0; i < 3; i++) { ++ strlcpy(card->s0num[i], sdef.num[i], ++ sizeof(card->s0num[0])); ++ } + break; + case ISDN_PTYPE_1TR6: + if (isdnloop_fake(card, "DRV1.04TC-1TR6-CAPI-CNS-BASIS-29.11.95", +@@ -1097,7 +1099,7 @@ isdnloop_start(isdnloop_card *card, isdnloop_sdef *sdefp) + spin_unlock_irqrestore(&card->isdnloop_lock, flags); + return -ENOMEM; + } +- strcpy(card->s0num[0], sdef.num[0]); ++ strlcpy(card->s0num[0], sdef.num[0], sizeof(card->s0num[0])); + card->s0num[1][0] = '\0'; + card->s0num[2][0] = '\0'; + break; +diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c +index e47dcb9..5cefb47 100644 +--- a/drivers/isdn/mISDN/socket.c ++++ b/drivers/isdn/mISDN/socket.c +@@ -117,7 +117,6 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + { + struct sk_buff *skb; + struct sock *sk = sock->sk; +- struct sockaddr_mISDN *maddr; + + int copied, err; + +@@ -135,9 +134,9 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + if (!skb) + return err; + +- if (msg->msg_namelen >= sizeof(struct sockaddr_mISDN)) { +- msg->msg_namelen = sizeof(struct sockaddr_mISDN); +- maddr = (struct sockaddr_mISDN *)msg->msg_name; ++ if (msg->msg_name) { ++ struct sockaddr_mISDN *maddr = msg->msg_name; ++ + maddr->family = AF_ISDN; + maddr->dev = _pms(sk)->dev->id; + if ((sk->sk_protocol == ISDN_P_LAPD_TE) || +@@ -150,11 +149,7 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + maddr->sapi = _pms(sk)->ch.addr & 0xFF; + maddr->tei = (_pms(sk)->ch.addr >> 8) & 0xFF; + } +- } else { +- if (msg->msg_namelen) +- printk(KERN_WARNING "%s: too small namelen %d\n", +- __func__, msg->msg_namelen); +- msg->msg_namelen = 0; ++ msg->msg_namelen = sizeof(*maddr); + } + + copied = skb->len + MISDN_HEADER_LEN; +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index e4109f6..8a0665d 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -5214,15 +5214,18 @@ raid5_show_group_thread_cnt(struct mddev *mddev, char *page) + return 0; + } + +-static int alloc_thread_groups(struct r5conf *conf, int cnt); ++static int alloc_thread_groups(struct r5conf *conf, int cnt, ++ int *group_cnt, ++ int *worker_cnt_per_group, ++ struct r5worker_group **worker_groups); + static ssize_t + raid5_store_group_thread_cnt(struct mddev *mddev, const char *page, size_t len) + { + struct r5conf *conf = mddev->private; + unsigned long new; + int err; +- struct r5worker_group *old_groups; +- int old_group_cnt; ++ struct r5worker_group *new_groups, *old_groups; ++ int group_cnt, worker_cnt_per_group; + + if (len >= PAGE_SIZE) + return -EINVAL; +@@ -5238,17 +5241,19 @@ raid5_store_group_thread_cnt(struct mddev *mddev, const char *page, size_t len) + mddev_suspend(mddev); + + old_groups = conf->worker_groups; +- old_group_cnt = conf->worker_cnt_per_group; +- + if (old_groups) + flush_workqueue(raid5_wq); + +- conf->worker_groups = NULL; +- err = alloc_thread_groups(conf, new); +- if (err) { +- conf->worker_groups = old_groups; +- conf->worker_cnt_per_group = old_group_cnt; +- } else { ++ err = alloc_thread_groups(conf, new, ++ &group_cnt, &worker_cnt_per_group, ++ &new_groups); ++ if (!err) { ++ spin_lock_irq(&conf->device_lock); ++ conf->group_cnt = group_cnt; ++ conf->worker_cnt_per_group = worker_cnt_per_group; ++ conf->worker_groups = new_groups; ++ spin_unlock_irq(&conf->device_lock); ++ + if (old_groups) + kfree(old_groups[0].workers); + kfree(old_groups); +@@ -5278,33 +5283,36 @@ static struct attribute_group raid5_attrs_group = { + .attrs = raid5_attrs, + }; + +-static int alloc_thread_groups(struct r5conf *conf, int cnt) ++static int alloc_thread_groups(struct r5conf *conf, int cnt, ++ int *group_cnt, ++ int *worker_cnt_per_group, ++ struct r5worker_group **worker_groups) + { + int i, j; + ssize_t size; + struct r5worker *workers; + +- conf->worker_cnt_per_group = cnt; ++ *worker_cnt_per_group = cnt; + if (cnt == 0) { +- conf->worker_groups = NULL; ++ *group_cnt = 0; ++ *worker_groups = NULL; + return 0; + } +- conf->group_cnt = num_possible_nodes(); ++ *group_cnt = num_possible_nodes(); + size = sizeof(struct r5worker) * cnt; +- workers = kzalloc(size * conf->group_cnt, GFP_NOIO); +- conf->worker_groups = kzalloc(sizeof(struct r5worker_group) * +- conf->group_cnt, GFP_NOIO); +- if (!conf->worker_groups || !workers) { ++ workers = kzalloc(size * *group_cnt, GFP_NOIO); ++ *worker_groups = kzalloc(sizeof(struct r5worker_group) * ++ *group_cnt, GFP_NOIO); ++ if (!*worker_groups || !workers) { + kfree(workers); +- kfree(conf->worker_groups); +- conf->worker_groups = NULL; ++ kfree(*worker_groups); + return -ENOMEM; + } + +- for (i = 0; i < conf->group_cnt; i++) { ++ for (i = 0; i < *group_cnt; i++) { + struct r5worker_group *group; + +- group = &conf->worker_groups[i]; ++ group = &(*worker_groups)[i]; + INIT_LIST_HEAD(&group->handle_list); + group->conf = conf; + group->workers = workers + i * cnt; +@@ -5462,6 +5470,8 @@ static struct r5conf *setup_conf(struct mddev *mddev) + struct md_rdev *rdev; + struct disk_info *disk; + char pers_name[6]; ++ int group_cnt, worker_cnt_per_group; ++ struct r5worker_group *new_group; + + if (mddev->new_level != 5 + && mddev->new_level != 4 +@@ -5496,7 +5506,12 @@ static struct r5conf *setup_conf(struct mddev *mddev) + if (conf == NULL) + goto abort; + /* Don't enable multi-threading by default*/ +- if (alloc_thread_groups(conf, 0)) ++ if (!alloc_thread_groups(conf, 0, &group_cnt, &worker_cnt_per_group, ++ &new_group)) { ++ conf->group_cnt = group_cnt; ++ conf->worker_cnt_per_group = worker_cnt_per_group; ++ conf->worker_groups = new_group; ++ } else + goto abort; + spin_lock_init(&conf->device_lock); + seqcount_init(&conf->gen_lock); +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index e883bfe..dd8057d 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -3395,20 +3395,20 @@ static void bond_set_rx_mode(struct net_device *bond_dev) + struct bonding *bond = netdev_priv(bond_dev); + struct slave *slave; + +- ASSERT_RTNL(); +- ++ rcu_read_lock(); + if (USES_PRIMARY(bond->params.mode)) { +- slave = rtnl_dereference(bond->curr_active_slave); ++ slave = rcu_dereference(bond->curr_active_slave); + if (slave) { + dev_uc_sync(slave->dev, bond_dev); + dev_mc_sync(slave->dev, bond_dev); + } + } else { +- bond_for_each_slave(bond, slave) { ++ bond_for_each_slave_rcu(bond, slave) { + dev_uc_sync_multiple(slave->dev, bond_dev); + dev_mc_sync_multiple(slave->dev, bond_dev); + } + } ++ rcu_read_unlock(); + } + + static int bond_neigh_init(struct neighbour *n) +diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c +index c29b836..b60f95b 100644 +--- a/drivers/net/bonding/bond_sysfs.c ++++ b/drivers/net/bonding/bond_sysfs.c +@@ -587,8 +587,9 @@ static ssize_t bonding_store_arp_interval(struct device *d, + goto out; + } + if (bond->params.mode == BOND_MODE_ALB || +- bond->params.mode == BOND_MODE_TLB) { +- pr_info("%s: ARP monitoring cannot be used with ALB/TLB. Only MII monitoring is supported on %s.\n", ++ bond->params.mode == BOND_MODE_TLB || ++ bond->params.mode == BOND_MODE_8023AD) { ++ pr_info("%s: ARP monitoring cannot be used with ALB/TLB/802.3ad. Only MII monitoring is supported on %s.\n", + bond->dev->name, bond->dev->name); + ret = -EINVAL; + goto out; +@@ -759,6 +760,8 @@ static ssize_t bonding_store_downdelay(struct device *d, + int new_value, ret = count; + struct bonding *bond = to_bond(d); + ++ if (!rtnl_trylock()) ++ return restart_syscall(); + if (!(bond->params.miimon)) { + pr_err("%s: Unable to set down delay as MII monitoring is disabled\n", + bond->dev->name); +@@ -792,6 +795,7 @@ static ssize_t bonding_store_downdelay(struct device *d, + } + + out: ++ rtnl_unlock(); + return ret; + } + static DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR, +@@ -814,6 +818,8 @@ static ssize_t bonding_store_updelay(struct device *d, + int new_value, ret = count; + struct bonding *bond = to_bond(d); + ++ if (!rtnl_trylock()) ++ return restart_syscall(); + if (!(bond->params.miimon)) { + pr_err("%s: Unable to set up delay as MII monitoring is disabled\n", + bond->dev->name); +@@ -847,6 +853,7 @@ static ssize_t bonding_store_updelay(struct device *d, + } + + out: ++ rtnl_unlock(); + return ret; + } + static DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR, +diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c +index 2c210ec..f2f6d85 100644 +--- a/drivers/net/ethernet/marvell/mv643xx_eth.c ++++ b/drivers/net/ethernet/marvell/mv643xx_eth.c +@@ -2890,6 +2890,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev) + PHY_INTERFACE_MODE_GMII); + if (!mp->phy) + err = -ENODEV; ++ else ++ phy_addr_set(mp, mp->phy->addr); + } else if (pd->phy_addr != MV643XX_ETH_PHY_NONE) { + mp->phy = phy_scan(mp, pd->phy_addr); + +diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c +index a071cda..0d087b0 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c +@@ -264,6 +264,10 @@ static void *mlx4_en_add(struct mlx4_dev *dev) + mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) + mdev->port_cnt++; + ++ /* Initialize time stamp mechanism */ ++ if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) ++ mlx4_en_init_timestamp(mdev); ++ + mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) { + if (!dev->caps.comp_pool) { + mdev->profile.prof[i].rx_ring_num = +@@ -301,10 +305,6 @@ static void *mlx4_en_add(struct mlx4_dev *dev) + mdev->pndev[i] = NULL; + } + +- /* Initialize time stamp mechanism */ +- if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) +- mlx4_en_init_timestamp(mdev); +- + return mdev; + + err_mr: +diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c +index d2e5919..0095af5 100644 +--- a/drivers/net/ethernet/realtek/8139cp.c ++++ b/drivers/net/ethernet/realtek/8139cp.c +@@ -678,9 +678,6 @@ static void cp_tx (struct cp_private *cp) + le32_to_cpu(txd->opts1) & 0xffff, + PCI_DMA_TODEVICE); + +- bytes_compl += skb->len; +- pkts_compl++; +- + if (status & LastFrag) { + if (status & (TxError | TxFIFOUnder)) { + netif_dbg(cp, tx_err, cp->dev, +@@ -702,6 +699,8 @@ static void cp_tx (struct cp_private *cp) + netif_dbg(cp, tx_done, cp->dev, + "tx done, slot %d\n", tx_tail); + } ++ bytes_compl += skb->len; ++ pkts_compl++; + dev_kfree_skb_irq(skb); + } + +diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c +index 3397cee..fb3f8dc 100644 +--- a/drivers/net/ethernet/realtek/r8169.c ++++ b/drivers/net/ethernet/realtek/r8169.c +@@ -3465,6 +3465,11 @@ static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp) + rtl_writephy(tp, 0x14, 0x9065); + rtl_writephy(tp, 0x14, 0x1065); + ++ /* Check ALDPS bit, disable it if enabled */ ++ rtl_writephy(tp, 0x1f, 0x0a43); ++ if (rtl_readphy(tp, 0x10) & 0x0004) ++ rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0004); ++ + rtl_writephy(tp, 0x1f, 0x0000); + } + +diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h +index 98eedb9..fc3e25c 100644 +--- a/drivers/net/ethernet/smsc/smc91x.h ++++ b/drivers/net/ethernet/smsc/smc91x.h +@@ -46,7 +46,8 @@ + defined(CONFIG_MACH_LITTLETON) ||\ + defined(CONFIG_MACH_ZYLONITE2) ||\ + defined(CONFIG_ARCH_VIPER) ||\ +- defined(CONFIG_MACH_STARGATE2) ++ defined(CONFIG_MACH_STARGATE2) ||\ ++ defined(CONFIG_ARCH_VERSATILE) + + #include <asm/mach-types.h> + +@@ -154,6 +155,8 @@ static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg) + #define SMC_outl(v, a, r) writel(v, (a) + (r)) + #define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) + #define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) ++#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) ++#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) + #define SMC_IRQ_FLAGS (-1) /* from resource */ + + /* We actually can't write halfwords properly if not word aligned */ +@@ -206,23 +209,6 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) + #define RPC_LSA_DEFAULT RPC_LED_TX_RX + #define RPC_LSB_DEFAULT RPC_LED_100_10 + +-#elif defined(CONFIG_ARCH_VERSATILE) +- +-#define SMC_CAN_USE_8BIT 1 +-#define SMC_CAN_USE_16BIT 1 +-#define SMC_CAN_USE_32BIT 1 +-#define SMC_NOWAIT 1 +- +-#define SMC_inb(a, r) readb((a) + (r)) +-#define SMC_inw(a, r) readw((a) + (r)) +-#define SMC_inl(a, r) readl((a) + (r)) +-#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +-#define SMC_outw(v, a, r) writew(v, (a) + (r)) +-#define SMC_outl(v, a, r) writel(v, (a) + (r)) +-#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) +-#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) +-#define SMC_IRQ_FLAGS (-1) /* from resource */ +- + #elif defined(CONFIG_MN10300) + + /* +diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c +index d022bf9..ad61d26 100644 +--- a/drivers/net/ethernet/via/via-velocity.c ++++ b/drivers/net/ethernet/via/via-velocity.c +@@ -2172,16 +2172,13 @@ static int velocity_poll(struct napi_struct *napi, int budget) + unsigned int rx_done; + unsigned long flags; + +- spin_lock_irqsave(&vptr->lock, flags); + /* + * Do rx and tx twice for performance (taken from the VIA + * out-of-tree driver). + */ +- rx_done = velocity_rx_srv(vptr, budget / 2); +- velocity_tx_srv(vptr); +- rx_done += velocity_rx_srv(vptr, budget - rx_done); ++ rx_done = velocity_rx_srv(vptr, budget); ++ spin_lock_irqsave(&vptr->lock, flags); + velocity_tx_srv(vptr); +- + /* If budget not fully consumed, exit the polling mode */ + if (rx_done < budget) { + napi_complete(napi); +@@ -2342,6 +2339,8 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu) + if (ret < 0) + goto out_free_tmp_vptr_1; + ++ napi_disable(&vptr->napi); ++ + spin_lock_irqsave(&vptr->lock, flags); + + netif_stop_queue(dev); +@@ -2362,6 +2361,8 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu) + + velocity_give_many_rx_descs(vptr); + ++ napi_enable(&vptr->napi); ++ + mac_enable_int(vptr->mac_regs); + netif_start_queue(dev); + +diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c +index 9dccb1e..dc76670 100644 +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -628,6 +628,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, + const struct iovec *iv, unsigned long total_len, + size_t count, int noblock) + { ++ int good_linear = SKB_MAX_HEAD(NET_IP_ALIGN); + struct sk_buff *skb; + struct macvlan_dev *vlan; + unsigned long len = total_len; +@@ -670,6 +671,8 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, + + if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) { + copylen = vnet_hdr.hdr_len ? vnet_hdr.hdr_len : GOODCOPY_LEN; ++ if (copylen > good_linear) ++ copylen = good_linear; + linear = copylen; + if (iov_pages(iv, vnet_hdr_len + copylen, count) + <= MAX_SKB_FRAGS) +@@ -678,7 +681,10 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, + + if (!zerocopy) { + copylen = len; +- linear = vnet_hdr.hdr_len; ++ if (vnet_hdr.hdr_len > good_linear) ++ linear = good_linear; ++ else ++ linear = vnet_hdr.hdr_len; + } + + skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen, +diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c +index 5f66e30..82ee6ed 100644 +--- a/drivers/net/ppp/pppoe.c ++++ b/drivers/net/ppp/pppoe.c +@@ -979,8 +979,6 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, + if (error < 0) + goto end; + +- m->msg_namelen = 0; +- + if (skb) { + total_len = min_t(size_t, total_len, skb->len); + error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len); +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 50e43e6..6327df2 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -1366,6 +1366,8 @@ static int team_user_linkup_option_get(struct team *team, + return 0; + } + ++static void __team_carrier_check(struct team *team); ++ + static int team_user_linkup_option_set(struct team *team, + struct team_gsetter_ctx *ctx) + { +@@ -1373,6 +1375,7 @@ static int team_user_linkup_option_set(struct team *team, + + port->user.linkup = ctx->data.bool_val; + team_refresh_port_linkup(port); ++ __team_carrier_check(port->team); + return 0; + } + +@@ -1392,6 +1395,7 @@ static int team_user_linkup_en_option_set(struct team *team, + + port->user.linkup_enabled = ctx->data.bool_val; + team_refresh_port_linkup(port); ++ __team_carrier_check(port->team); + return 0; + } + +diff --git a/drivers/net/tun.c b/drivers/net/tun.c +index 7cb105c..782e38b 100644 +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -981,6 +981,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, + struct sk_buff *skb; + size_t len = total_len, align = NET_SKB_PAD, linear; + struct virtio_net_hdr gso = { 0 }; ++ int good_linear; + int offset = 0; + int copylen; + bool zerocopy = false; +@@ -1021,12 +1022,16 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, + return -EINVAL; + } + ++ good_linear = SKB_MAX_HEAD(align); ++ + if (msg_control) { + /* There are 256 bytes to be copied in skb, so there is + * enough room for skb expand head in case it is used. + * The rest of the buffer is mapped from userspace. + */ + copylen = gso.hdr_len ? gso.hdr_len : GOODCOPY_LEN; ++ if (copylen > good_linear) ++ copylen = good_linear; + linear = copylen; + if (iov_pages(iv, offset + copylen, count) <= MAX_SKB_FRAGS) + zerocopy = true; +@@ -1034,7 +1039,10 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, + + if (!zerocopy) { + copylen = len; +- linear = gso.hdr_len; ++ if (gso.hdr_len > good_linear) ++ linear = good_linear; ++ else ++ linear = gso.hdr_len; + } + + skb = tun_alloc_skb(tfile, align, copylen, linear, noblock); +diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c +index 90a429b..8494bb5 100644 +--- a/drivers/net/usb/usbnet.c ++++ b/drivers/net/usb/usbnet.c +@@ -204,9 +204,6 @@ static void intr_complete (struct urb *urb) + break; + } + +- if (!netif_running (dev->net)) +- return; +- + status = usb_submit_urb (urb, GFP_ATOMIC); + if (status != 0) + netif_err(dev, timer, dev->net, +diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h +index fa33b5e..e3eb952 100644 +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -52,6 +52,7 @@ + * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) + * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) + * RF5592 2.4G/5G 2T2R ++ * RF3070 2.4G 1T1R + * RF5360 2.4G 1T1R + * RF5370 2.4G 1T1R + * RF5390 2.4G 1T1R +@@ -70,6 +71,7 @@ + #define RF3322 0x000c + #define RF3053 0x000d + #define RF5592 0x000f ++#define RF3070 0x3070 + #define RF3290 0x3290 + #define RF5360 0x5360 + #define RF5370 0x5370 +diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c +index 1400787..446eade 100644 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -3152,6 +3152,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, + case RF3322: + rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info); + break; ++ case RF3070: + case RF5360: + case RF5370: + case RF5372: +@@ -3166,7 +3167,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, + rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); + } + +- if (rt2x00_rf(rt2x00dev, RF3290) || ++ if (rt2x00_rf(rt2x00dev, RF3070) || ++ rt2x00_rf(rt2x00dev, RF3290) || + rt2x00_rf(rt2x00dev, RF3322) || + rt2x00_rf(rt2x00dev, RF5360) || + rt2x00_rf(rt2x00dev, RF5370) || +@@ -4264,6 +4266,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev) + rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); + break; + case RF3053: ++ case RF3070: + case RF3290: + case RF5360: + case RF5370: +@@ -7024,6 +7027,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) + case RF3022: + case RF3052: + case RF3053: ++ case RF3070: + case RF3290: + case RF3320: + case RF3322: +@@ -7546,6 +7550,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) + rt2x00_rf(rt2x00dev, RF2020) || + rt2x00_rf(rt2x00dev, RF3021) || + rt2x00_rf(rt2x00dev, RF3022) || ++ rt2x00_rf(rt2x00dev, RF3070) || + rt2x00_rf(rt2x00dev, RF3290) || + rt2x00_rf(rt2x00dev, RF3320) || + rt2x00_rf(rt2x00dev, RF3322) || +@@ -7674,6 +7679,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) + case RF3320: + case RF3052: + case RF3053: ++ case RF3070: + case RF3290: + case RF5360: + case RF5370: +diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c +index 900da4b..6255850 100644 +--- a/drivers/net/xen-netback/netback.c ++++ b/drivers/net/xen-netback/netback.c +@@ -39,6 +39,7 @@ + #include <linux/udp.h> + + #include <net/tcp.h> ++#include <net/ip6_checksum.h> + + #include <xen/xen.h> + #include <xen/events.h> +diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c +index ed0834e..ab69245 100644 +--- a/drivers/usb/musb/davinci.c ++++ b/drivers/usb/musb/davinci.c +@@ -509,7 +509,7 @@ static u64 davinci_dmamask = DMA_BIT_MASK(32); + + static int davinci_probe(struct platform_device *pdev) + { +- struct resource musb_resources[2]; ++ struct resource musb_resources[3]; + struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct platform_device *musb; + struct davinci_glue *glue; +@@ -567,6 +567,15 @@ static int davinci_probe(struct platform_device *pdev) + musb_resources[1].end = pdev->resource[1].end; + musb_resources[1].flags = pdev->resource[1].flags; + ++ /* ++ * For DM6467 3 resources are passed. A placeholder for the 3rd ++ * resource is always there, so it's safe to always copy it... ++ */ ++ musb_resources[2].name = pdev->resource[2].name; ++ musb_resources[2].start = pdev->resource[2].start; ++ musb_resources[2].end = pdev->resource[2].end; ++ musb_resources[2].flags = pdev->resource[2].flags; ++ + ret = platform_device_add_resources(musb, musb_resources, + ARRAY_SIZE(musb_resources)); + if (ret) { +diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c +index 6ad02f5..3dcf66f 100644 +--- a/drivers/usb/wusbcore/wa-xfer.c ++++ b/drivers/usb/wusbcore/wa-xfer.c +@@ -91,7 +91,8 @@ + #include "wusbhc.h" + + enum { +- WA_SEGS_MAX = 255, ++ /* [WUSB] section 8.3.3 allocates 7 bits for the segment index. */ ++ WA_SEGS_MAX = 128, + }; + + enum wa_seg_status { +@@ -446,7 +447,7 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer, + } + xfer->seg_size = (xfer->seg_size / maxpktsize) * maxpktsize; + xfer->segs = DIV_ROUND_UP(urb->transfer_buffer_length, xfer->seg_size); +- if (xfer->segs >= WA_SEGS_MAX) { ++ if (xfer->segs > WA_SEGS_MAX) { + dev_err(dev, "BUG? ops, number of segments %d bigger than %d\n", + (int)(urb->transfer_buffer_length / xfer->seg_size), + WA_SEGS_MAX); +diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c +index 6157f74..ec7fc87 100644 +--- a/drivers/video/kyro/fbdev.c ++++ b/drivers/video/kyro/fbdev.c +@@ -625,15 +625,15 @@ static int kyrofb_ioctl(struct fb_info *info, + } + break; + case KYRO_IOCTL_UVSTRIDE: +- if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long))) ++ if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(deviceInfo.ulOverlayUVStride))) + return -EFAULT; + break; + case KYRO_IOCTL_STRIDE: +- if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(unsigned long))) ++ if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(deviceInfo.ulOverlayStride))) + return -EFAULT; + break; + case KYRO_IOCTL_OVERLAY_OFFSET: +- if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(unsigned long))) ++ if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(deviceInfo.ulOverlayOffset))) + return -EFAULT; + break; + } +diff --git a/fs/aio.c b/fs/aio.c +index 067e3d3..6efb7f6 100644 +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -36,10 +36,10 @@ + #include <linux/eventfd.h> + #include <linux/blkdev.h> + #include <linux/compat.h> +-#include <linux/anon_inodes.h> + #include <linux/migrate.h> + #include <linux/ramfs.h> + #include <linux/percpu-refcount.h> ++#include <linux/mount.h> + + #include <asm/kmap_types.h> + #include <asm/uaccess.h> +@@ -80,6 +80,8 @@ struct kioctx { + struct percpu_ref users; + atomic_t dead; + ++ struct percpu_ref reqs; ++ + unsigned long user_id; + + struct __percpu kioctx_cpu *cpu; +@@ -107,7 +109,6 @@ struct kioctx { + struct page **ring_pages; + long nr_pages; + +- struct rcu_head rcu_head; + struct work_struct free_work; + + struct { +@@ -152,12 +153,67 @@ unsigned long aio_max_nr = 0x10000; /* system wide maximum number of aio request + static struct kmem_cache *kiocb_cachep; + static struct kmem_cache *kioctx_cachep; + ++static struct vfsmount *aio_mnt; ++ ++static const struct file_operations aio_ring_fops; ++static const struct address_space_operations aio_ctx_aops; ++ ++static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) ++{ ++ struct qstr this = QSTR_INIT("[aio]", 5); ++ struct file *file; ++ struct path path; ++ struct inode *inode = alloc_anon_inode(aio_mnt->mnt_sb); ++ if (IS_ERR(inode)) ++ return ERR_CAST(inode); ++ ++ inode->i_mapping->a_ops = &aio_ctx_aops; ++ inode->i_mapping->private_data = ctx; ++ inode->i_size = PAGE_SIZE * nr_pages; ++ ++ path.dentry = d_alloc_pseudo(aio_mnt->mnt_sb, &this); ++ if (!path.dentry) { ++ iput(inode); ++ return ERR_PTR(-ENOMEM); ++ } ++ path.mnt = mntget(aio_mnt); ++ ++ d_instantiate(path.dentry, inode); ++ file = alloc_file(&path, FMODE_READ | FMODE_WRITE, &aio_ring_fops); ++ if (IS_ERR(file)) { ++ path_put(&path); ++ return file; ++ } ++ ++ file->f_flags = O_RDWR; ++ file->private_data = ctx; ++ return file; ++} ++ ++static struct dentry *aio_mount(struct file_system_type *fs_type, ++ int flags, const char *dev_name, void *data) ++{ ++ static const struct dentry_operations ops = { ++ .d_dname = simple_dname, ++ }; ++ return mount_pseudo(fs_type, "aio:", NULL, &ops, 0xa10a10a1); ++} ++ + /* aio_setup + * Creates the slab caches used by the aio routines, panic on + * failure as this is done early during the boot sequence. + */ + static int __init aio_setup(void) + { ++ static struct file_system_type aio_fs = { ++ .name = "aio", ++ .mount = aio_mount, ++ .kill_sb = kill_anon_super, ++ }; ++ aio_mnt = kern_mount(&aio_fs); ++ if (IS_ERR(aio_mnt)) ++ panic("Failed to create aio fs mount."); ++ + kiocb_cachep = KMEM_CACHE(kiocb, SLAB_HWCACHE_ALIGN|SLAB_PANIC); + kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC); + +@@ -195,8 +251,10 @@ static void aio_free_ring(struct kioctx *ctx) + + put_aio_ring_file(ctx); + +- if (ctx->ring_pages && ctx->ring_pages != ctx->internal_pages) ++ if (ctx->ring_pages && ctx->ring_pages != ctx->internal_pages) { + kfree(ctx->ring_pages); ++ ctx->ring_pages = NULL; ++ } + } + + static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma) +@@ -283,16 +341,12 @@ static int aio_setup_ring(struct kioctx *ctx) + if (nr_pages < 0) + return -EINVAL; + +- file = anon_inode_getfile_private("[aio]", &aio_ring_fops, ctx, O_RDWR); ++ file = aio_private_file(ctx, nr_pages); + if (IS_ERR(file)) { + ctx->aio_ring_file = NULL; + return -EAGAIN; + } + +- file->f_inode->i_mapping->a_ops = &aio_ctx_aops; +- file->f_inode->i_mapping->private_data = ctx; +- file->f_inode->i_size = PAGE_SIZE * (loff_t)nr_pages; +- + for (i = 0; i < nr_pages; i++) { + struct page *page; + page = find_or_create_page(file->f_inode->i_mapping, +@@ -313,8 +367,10 @@ static int aio_setup_ring(struct kioctx *ctx) + if (nr_pages > AIO_RING_PAGES) { + ctx->ring_pages = kcalloc(nr_pages, sizeof(struct page *), + GFP_KERNEL); +- if (!ctx->ring_pages) ++ if (!ctx->ring_pages) { ++ put_aio_ring_file(ctx); + return -ENOMEM; ++ } + } + + ctx->mmap_size = nr_pages * PAGE_SIZE; +@@ -412,26 +468,34 @@ static int kiocb_cancel(struct kioctx *ctx, struct kiocb *kiocb) + return cancel(kiocb); + } + +-static void free_ioctx_rcu(struct rcu_head *head) ++static void free_ioctx(struct work_struct *work) + { +- struct kioctx *ctx = container_of(head, struct kioctx, rcu_head); ++ struct kioctx *ctx = container_of(work, struct kioctx, free_work); + ++ pr_debug("freeing %p\n", ctx); ++ ++ aio_free_ring(ctx); + free_percpu(ctx->cpu); + kmem_cache_free(kioctx_cachep, ctx); + } + ++static void free_ioctx_reqs(struct percpu_ref *ref) ++{ ++ struct kioctx *ctx = container_of(ref, struct kioctx, reqs); ++ ++ INIT_WORK(&ctx->free_work, free_ioctx); ++ schedule_work(&ctx->free_work); ++} ++ + /* + * When this function runs, the kioctx has been removed from the "hash table" + * and ctx->users has dropped to 0, so we know no more kiocbs can be submitted - + * now it's safe to cancel any that need to be. + */ +-static void free_ioctx(struct work_struct *work) ++static void free_ioctx_users(struct percpu_ref *ref) + { +- struct kioctx *ctx = container_of(work, struct kioctx, free_work); +- struct aio_ring *ring; ++ struct kioctx *ctx = container_of(ref, struct kioctx, users); + struct kiocb *req; +- unsigned cpu, avail; +- DEFINE_WAIT(wait); + + spin_lock_irq(&ctx->ctx_lock); + +@@ -445,54 +509,8 @@ static void free_ioctx(struct work_struct *work) + + spin_unlock_irq(&ctx->ctx_lock); + +- for_each_possible_cpu(cpu) { +- struct kioctx_cpu *kcpu = per_cpu_ptr(ctx->cpu, cpu); +- +- atomic_add(kcpu->reqs_available, &ctx->reqs_available); +- kcpu->reqs_available = 0; +- } +- +- while (1) { +- prepare_to_wait(&ctx->wait, &wait, TASK_UNINTERRUPTIBLE); +- +- ring = kmap_atomic(ctx->ring_pages[0]); +- avail = (ring->head <= ring->tail) +- ? ring->tail - ring->head +- : ctx->nr_events - ring->head + ring->tail; +- +- atomic_add(avail, &ctx->reqs_available); +- ring->head = ring->tail; +- kunmap_atomic(ring); +- +- if (atomic_read(&ctx->reqs_available) >= ctx->nr_events - 1) +- break; +- +- schedule(); +- } +- finish_wait(&ctx->wait, &wait); +- +- WARN_ON(atomic_read(&ctx->reqs_available) > ctx->nr_events - 1); +- +- aio_free_ring(ctx); +- +- pr_debug("freeing %p\n", ctx); +- +- /* +- * Here the call_rcu() is between the wait_event() for reqs_active to +- * hit 0, and freeing the ioctx. +- * +- * aio_complete() decrements reqs_active, but it has to touch the ioctx +- * after to issue a wakeup so we use rcu. +- */ +- call_rcu(&ctx->rcu_head, free_ioctx_rcu); +-} +- +-static void free_ioctx_ref(struct percpu_ref *ref) +-{ +- struct kioctx *ctx = container_of(ref, struct kioctx, users); +- +- INIT_WORK(&ctx->free_work, free_ioctx); +- schedule_work(&ctx->free_work); ++ percpu_ref_kill(&ctx->reqs); ++ percpu_ref_put(&ctx->reqs); + } + + static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) +@@ -551,6 +569,16 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) + } + } + ++static void aio_nr_sub(unsigned nr) ++{ ++ spin_lock(&aio_nr_lock); ++ if (WARN_ON(aio_nr - nr > aio_nr)) ++ aio_nr = 0; ++ else ++ aio_nr -= nr; ++ spin_unlock(&aio_nr_lock); ++} ++ + /* ioctx_alloc + * Allocates and initializes an ioctx. Returns an ERR_PTR if it failed. + */ +@@ -588,8 +616,11 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) + + ctx->max_reqs = nr_events; + +- if (percpu_ref_init(&ctx->users, free_ioctx_ref)) +- goto out_freectx; ++ if (percpu_ref_init(&ctx->users, free_ioctx_users)) ++ goto err; ++ ++ if (percpu_ref_init(&ctx->reqs, free_ioctx_reqs)) ++ goto err; + + spin_lock_init(&ctx->ctx_lock); + spin_lock_init(&ctx->completion_lock); +@@ -600,10 +631,10 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) + + ctx->cpu = alloc_percpu(struct kioctx_cpu); + if (!ctx->cpu) +- goto out_freeref; ++ goto err; + + if (aio_setup_ring(ctx) < 0) +- goto out_freepcpu; ++ goto err; + + atomic_set(&ctx->reqs_available, ctx->nr_events - 1); + ctx->req_batch = (ctx->nr_events - 1) / (num_possible_cpus() * 4); +@@ -615,7 +646,8 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) + if (aio_nr + nr_events > (aio_max_nr * 2UL) || + aio_nr + nr_events < aio_nr) { + spin_unlock(&aio_nr_lock); +- goto out_cleanup; ++ err = -EAGAIN; ++ goto err_ctx; + } + aio_nr += ctx->max_reqs; + spin_unlock(&aio_nr_lock); +@@ -624,23 +656,20 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) + + err = ioctx_add_table(ctx, mm); + if (err) +- goto out_cleanup_put; ++ goto err_cleanup; + + pr_debug("allocated ioctx %p[%ld]: mm=%p mask=0x%x\n", + ctx, ctx->user_id, mm, ctx->nr_events); + return ctx; + +-out_cleanup_put: +- percpu_ref_put(&ctx->users); +-out_cleanup: +- err = -EAGAIN; ++err_cleanup: ++ aio_nr_sub(ctx->max_reqs); ++err_ctx: + aio_free_ring(ctx); +-out_freepcpu: ++err: + free_percpu(ctx->cpu); +-out_freeref: ++ free_percpu(ctx->reqs.pcpu_count); + free_percpu(ctx->users.pcpu_count); +-out_freectx: +- put_aio_ring_file(ctx); + kmem_cache_free(kioctx_cachep, ctx); + pr_debug("error allocating ioctx %d\n", err); + return ERR_PTR(err); +@@ -675,10 +704,7 @@ static void kill_ioctx(struct mm_struct *mm, struct kioctx *ctx) + * -EAGAIN with no ioctxs actually in use (as far as userspace + * could tell). + */ +- spin_lock(&aio_nr_lock); +- BUG_ON(aio_nr - ctx->max_reqs > aio_nr); +- aio_nr -= ctx->max_reqs; +- spin_unlock(&aio_nr_lock); ++ aio_nr_sub(ctx->max_reqs); + + if (ctx->mmap_size) + vm_munmap(ctx->mmap_base, ctx->mmap_size); +@@ -810,6 +836,8 @@ static inline struct kiocb *aio_get_req(struct kioctx *ctx) + if (unlikely(!req)) + goto out_put; + ++ percpu_ref_get(&ctx->reqs); ++ + req->ki_ctx = ctx; + return req; + out_put: +@@ -879,12 +907,6 @@ void aio_complete(struct kiocb *iocb, long res, long res2) + return; + } + +- /* +- * Take rcu_read_lock() in case the kioctx is being destroyed, as we +- * need to issue a wakeup after incrementing reqs_available. +- */ +- rcu_read_lock(); +- + if (iocb->ki_list.next) { + unsigned long flags; + +@@ -959,7 +981,7 @@ void aio_complete(struct kiocb *iocb, long res, long res2) + if (waitqueue_active(&ctx->wait)) + wake_up(&ctx->wait); + +- rcu_read_unlock(); ++ percpu_ref_put(&ctx->reqs); + } + EXPORT_SYMBOL(aio_complete); + +@@ -1370,6 +1392,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, + return 0; + out_put_req: + put_reqs_available(ctx, 1); ++ percpu_ref_put(&ctx->reqs); + kiocb_free(req); + return ret; + } +diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c +index 85c9618..22f9698 100644 +--- a/fs/anon_inodes.c ++++ b/fs/anon_inodes.c +@@ -24,7 +24,6 @@ + + static struct vfsmount *anon_inode_mnt __read_mostly; + static struct inode *anon_inode_inode; +-static const struct file_operations anon_inode_fops; + + /* + * anon_inodefs_dname() is called from d_path(). +@@ -39,51 +38,6 @@ static const struct dentry_operations anon_inodefs_dentry_operations = { + .d_dname = anon_inodefs_dname, + }; + +-/* +- * nop .set_page_dirty method so that people can use .page_mkwrite on +- * anon inodes. +- */ +-static int anon_set_page_dirty(struct page *page) +-{ +- return 0; +-}; +- +-static const struct address_space_operations anon_aops = { +- .set_page_dirty = anon_set_page_dirty, +-}; +- +-/* +- * A single inode exists for all anon_inode files. Contrary to pipes, +- * anon_inode inodes have no associated per-instance data, so we need +- * only allocate one of them. +- */ +-static struct inode *anon_inode_mkinode(struct super_block *s) +-{ +- struct inode *inode = new_inode_pseudo(s); +- +- if (!inode) +- return ERR_PTR(-ENOMEM); +- +- inode->i_ino = get_next_ino(); +- inode->i_fop = &anon_inode_fops; +- +- inode->i_mapping->a_ops = &anon_aops; +- +- /* +- * Mark the inode dirty from the very beginning, +- * that way it will never be moved to the dirty +- * list because mark_inode_dirty() will think +- * that it already _is_ on the dirty list. +- */ +- inode->i_state = I_DIRTY; +- inode->i_mode = S_IRUSR | S_IWUSR; +- inode->i_uid = current_fsuid(); +- inode->i_gid = current_fsgid(); +- inode->i_flags |= S_PRIVATE; +- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; +- return inode; +-} +- + static struct dentry *anon_inodefs_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data) + { +@@ -92,7 +46,7 @@ static struct dentry *anon_inodefs_mount(struct file_system_type *fs_type, + &anon_inodefs_dentry_operations, ANON_INODE_FS_MAGIC); + if (!IS_ERR(root)) { + struct super_block *s = root->d_sb; +- anon_inode_inode = anon_inode_mkinode(s); ++ anon_inode_inode = alloc_anon_inode(s); + if (IS_ERR(anon_inode_inode)) { + dput(root); + deactivate_locked_super(s); +@@ -134,7 +88,7 @@ struct file *anon_inode_getfile_private(const char *name, + if (fops->owner && !try_module_get(fops->owner)) + return ERR_PTR(-ENOENT); + +- inode = anon_inode_mkinode(anon_inode_mnt->mnt_sb); ++ inode = alloc_anon_inode(anon_inode_mnt->mnt_sb); + if (IS_ERR(inode)) { + file = ERR_PTR(-ENOMEM); + goto err_module; +diff --git a/fs/libfs.c b/fs/libfs.c +index 3a3a9b5..193e0c2 100644 +--- a/fs/libfs.c ++++ b/fs/libfs.c +@@ -993,3 +993,46 @@ EXPORT_SYMBOL_GPL(simple_attr_open); + EXPORT_SYMBOL_GPL(simple_attr_release); + EXPORT_SYMBOL_GPL(simple_attr_read); + EXPORT_SYMBOL_GPL(simple_attr_write); ++ ++/* ++ * nop .set_page_dirty method so that people can use .page_mkwrite on ++ * anon inodes. ++ */ ++static int anon_set_page_dirty(struct page *page) ++{ ++ return 0; ++}; ++ ++/* ++ * A single inode exists for all anon_inode files. Contrary to pipes, ++ * anon_inode inodes have no associated per-instance data, so we need ++ * only allocate one of them. ++ */ ++struct inode *alloc_anon_inode(struct super_block *s) ++{ ++ static const struct address_space_operations anon_aops = { ++ .set_page_dirty = anon_set_page_dirty, ++ }; ++ struct inode *inode = new_inode_pseudo(s); ++ ++ if (!inode) ++ return ERR_PTR(-ENOMEM); ++ ++ inode->i_ino = get_next_ino(); ++ inode->i_mapping->a_ops = &anon_aops; ++ ++ /* ++ * Mark the inode dirty from the very beginning, ++ * that way it will never be moved to the dirty ++ * list because mark_inode_dirty() will think ++ * that it already _is_ on the dirty list. ++ */ ++ inode->i_state = I_DIRTY; ++ inode->i_mode = S_IRUSR | S_IWUSR; ++ inode->i_uid = current_fsuid(); ++ inode->i_gid = current_fsgid(); ++ inode->i_flags |= S_PRIVATE; ++ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; ++ return inode; ++} ++EXPORT_SYMBOL(alloc_anon_inode); +diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c +index 668e8f4..2e1e6c3 100644 +--- a/fs/xfs/xfs_ioctl.c ++++ b/fs/xfs/xfs_ioctl.c +@@ -1717,6 +1717,12 @@ xfs_file_ioctl( + if (mp->m_flags & XFS_MOUNT_RDONLY) + return -XFS_ERROR(EROFS); + ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ ++ if (mp->m_flags & XFS_MOUNT_RDONLY) ++ return -XFS_ERROR(EROFS); ++ + if (copy_from_user(&eofb, arg, sizeof(eofb))) + return -XFS_ERROR(EFAULT); + +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 3f40547..fefa7b0 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -2562,6 +2562,7 @@ extern int simple_write_begin(struct file *file, struct address_space *mapping, + extern int simple_write_end(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned copied, + struct page *page, void *fsdata); ++extern struct inode *alloc_anon_inode(struct super_block *); + + extern struct dentry *simple_lookup(struct inode *, struct dentry *, unsigned int flags); + extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *); +diff --git a/include/linux/net.h b/include/linux/net.h +index 4f27575..8bd9d92 100644 +--- a/include/linux/net.h ++++ b/include/linux/net.h +@@ -163,6 +163,14 @@ struct proto_ops { + #endif + int (*sendmsg) (struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len); ++ /* Notes for implementing recvmsg: ++ * =============================== ++ * msg->msg_namelen should get updated by the recvmsg handlers ++ * iff msg_name != NULL. It is by default 0 to prevent ++ * returning uninitialized memory to user space. The recvfrom ++ * handlers can assume that msg.msg_name is either NULL or has ++ * a minimum size of sizeof(struct sockaddr_storage). ++ */ + int (*recvmsg) (struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len, + int flags); +diff --git a/include/linux/random.h b/include/linux/random.h +index 6312dd9..bf9085e 100644 +--- a/include/linux/random.h ++++ b/include/linux/random.h +@@ -50,9 +50,9 @@ static inline void prandom_seed_state(struct rnd_state *state, u64 seed) + { + u32 i = (seed >> 32) ^ (seed << 10) ^ seed; + +- state->s1 = __seed(i, 1); +- state->s2 = __seed(i, 7); +- state->s3 = __seed(i, 15); ++ state->s1 = __seed(i, 2); ++ state->s2 = __seed(i, 8); ++ state->s3 = __seed(i, 16); + } + + #ifdef CONFIG_ARCH_RANDOM +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index c2d8933..f66f346 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -333,11 +333,6 @@ typedef unsigned int sk_buff_data_t; + typedef unsigned char *sk_buff_data_t; + #endif + +-#if defined(CONFIG_NF_DEFRAG_IPV4) || defined(CONFIG_NF_DEFRAG_IPV4_MODULE) || \ +- defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE) +-#define NET_SKBUFF_NF_DEFRAG_NEEDED 1 +-#endif +- + /** + * struct sk_buff - socket buffer + * @next: Next buffer in list +@@ -370,7 +365,6 @@ typedef unsigned char *sk_buff_data_t; + * @protocol: Packet protocol from driver + * @destructor: Destruct function + * @nfct: Associated connection, if any +- * @nfct_reasm: netfilter conntrack re-assembly pointer + * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c + * @skb_iif: ifindex of device we arrived on + * @tc_index: Traffic control index +@@ -459,9 +453,6 @@ struct sk_buff { + #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + struct nf_conntrack *nfct; + #endif +-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED +- struct sk_buff *nfct_reasm; +-#endif + #ifdef CONFIG_BRIDGE_NETFILTER + struct nf_bridge_info *nf_bridge; + #endif +@@ -2605,18 +2596,6 @@ static inline void nf_conntrack_get(struct nf_conntrack *nfct) + atomic_inc(&nfct->use); + } + #endif +-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED +-static inline void nf_conntrack_get_reasm(struct sk_buff *skb) +-{ +- if (skb) +- atomic_inc(&skb->users); +-} +-static inline void nf_conntrack_put_reasm(struct sk_buff *skb) +-{ +- if (skb) +- kfree_skb(skb); +-} +-#endif + #ifdef CONFIG_BRIDGE_NETFILTER + static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge) + { +@@ -2635,10 +2614,6 @@ static inline void nf_reset(struct sk_buff *skb) + nf_conntrack_put(skb->nfct); + skb->nfct = NULL; + #endif +-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED +- nf_conntrack_put_reasm(skb->nfct_reasm); +- skb->nfct_reasm = NULL; +-#endif + #ifdef CONFIG_BRIDGE_NETFILTER + nf_bridge_put(skb->nf_bridge); + skb->nf_bridge = NULL; +@@ -2660,10 +2635,6 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src) + nf_conntrack_get(src->nfct); + dst->nfctinfo = src->nfctinfo; + #endif +-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED +- dst->nfct_reasm = src->nfct_reasm; +- nf_conntrack_get_reasm(src->nfct_reasm); +-#endif + #ifdef CONFIG_BRIDGE_NETFILTER + dst->nf_bridge = src->nf_bridge; + nf_bridge_get(src->nf_bridge); +@@ -2675,9 +2646,6 @@ static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src) + #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + nf_conntrack_put(dst->nfct); + #endif +-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED +- nf_conntrack_put_reasm(dst->nfct_reasm); +-#endif + #ifdef CONFIG_BRIDGE_NETFILTER + nf_bridge_put(dst->nf_bridge); + #endif +diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h +index 1855f0a..c557c6d 100644 +--- a/include/linux/vm_event_item.h ++++ b/include/linux/vm_event_item.h +@@ -39,6 +39,7 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT, + PAGEOUTRUN, ALLOCSTALL, PGROTATED, + #ifdef CONFIG_NUMA_BALANCING + NUMA_PTE_UPDATES, ++ NUMA_HUGE_PTE_UPDATES, + NUMA_HINT_FAULTS, + NUMA_HINT_FAULTS_LOCAL, + NUMA_PAGE_MIGRATE, +diff --git a/include/net/ip.h b/include/net/ip.h +index 5e52688..301f10c 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -464,7 +464,7 @@ extern int compat_ip_getsockopt(struct sock *sk, int level, + int optname, char __user *optval, int __user *optlen); + extern int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *)); + +-extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len); ++extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len); + extern void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, + __be16 port, u32 info, u8 *payload); + extern void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport, +diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h +index 9c4d37e..772252d 100644 +--- a/include/net/ip_vs.h ++++ b/include/net/ip_vs.h +@@ -109,7 +109,6 @@ extern int ip_vs_conn_tab_size; + struct ip_vs_iphdr { + __u32 len; /* IPv4 simply where L4 starts + IPv6 where L4 Transport Header starts */ +- __u32 thoff_reasm; /* Transport Header Offset in nfct_reasm skb */ + __u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/ + __s16 protocol; + __s32 flags; +@@ -117,34 +116,12 @@ struct ip_vs_iphdr { + union nf_inet_addr daddr; + }; + +-/* Dependency to module: nf_defrag_ipv6 */ +-#if defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE) +-static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb) +-{ +- return skb->nfct_reasm; +-} +-static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset, +- int len, void *buffer, +- const struct ip_vs_iphdr *ipvsh) +-{ +- if (unlikely(ipvsh->fragoffs && skb_nfct_reasm(skb))) +- return skb_header_pointer(skb_nfct_reasm(skb), +- ipvsh->thoff_reasm, len, buffer); +- +- return skb_header_pointer(skb, offset, len, buffer); +-} +-#else +-static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb) +-{ +- return NULL; +-} + static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset, + int len, void *buffer, + const struct ip_vs_iphdr *ipvsh) + { + return skb_header_pointer(skb, offset, len, buffer); + } +-#endif + + static inline void + ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr) +@@ -171,19 +148,12 @@ ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr) + (struct ipv6hdr *)skb_network_header(skb); + iphdr->saddr.in6 = iph->saddr; + iphdr->daddr.in6 = iph->daddr; +- /* ipv6_find_hdr() updates len, flags, thoff_reasm */ +- iphdr->thoff_reasm = 0; ++ /* ipv6_find_hdr() updates len, flags */ + iphdr->len = 0; + iphdr->flags = 0; + iphdr->protocol = ipv6_find_hdr(skb, &iphdr->len, -1, + &iphdr->fragoffs, + &iphdr->flags); +- /* get proto from re-assembled packet and it's offset */ +- if (skb_nfct_reasm(skb)) +- iphdr->protocol = ipv6_find_hdr(skb_nfct_reasm(skb), +- &iphdr->thoff_reasm, +- -1, NULL, NULL); +- + } else + #endif + { +diff --git a/include/net/ipv6.h b/include/net/ipv6.h +index bbf1c8f..1f96efd 100644 +--- a/include/net/ipv6.h ++++ b/include/net/ipv6.h +@@ -802,8 +802,10 @@ extern int compat_ipv6_getsockopt(struct sock *sk, + extern int ip6_datagram_connect(struct sock *sk, + struct sockaddr *addr, int addr_len); + +-extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len); +-extern int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len); ++extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, ++ int *addr_len); ++extern int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len, ++ int *addr_len); + extern void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port, + u32 info, u8 *payload); + extern void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info); +diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h +index fd79c9a..17920d8 100644 +--- a/include/net/netfilter/ipv6/nf_defrag_ipv6.h ++++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h +@@ -6,10 +6,7 @@ extern void nf_defrag_ipv6_enable(void); + extern int nf_ct_frag6_init(void); + extern void nf_ct_frag6_cleanup(void); + extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user); +-extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, +- struct net_device *in, +- struct net_device *out, +- int (*okfn)(struct sk_buff *)); ++extern void nf_ct_frag6_consume_orig(struct sk_buff *skb); + + struct inet_frags_ctl; + +diff --git a/include/net/ping.h b/include/net/ping.h +index 5db0224..2b496e9 100644 +--- a/include/net/ping.h ++++ b/include/net/ping.h +@@ -31,7 +31,8 @@ + + /* Compatibility glue so we can support IPv6 when it's compiled as a module */ + struct pingv6_ops { +- int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len); ++ int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len, ++ int *addr_len); + int (*ip6_datagram_recv_ctl)(struct sock *sk, struct msghdr *msg, + struct sk_buff *skb); + int (*icmpv6_err_convert)(u8 type, u8 code, int *err); +diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h +index 9b82913..66f925d 100644 +--- a/include/uapi/linux/pkt_sched.h ++++ b/include/uapi/linux/pkt_sched.h +@@ -759,13 +759,14 @@ enum { + + TCA_FQ_RATE_ENABLE, /* enable/disable rate limiting */ + +- TCA_FQ_FLOW_DEFAULT_RATE,/* for sockets with unspecified sk_rate, +- * use the following rate +- */ ++ TCA_FQ_FLOW_DEFAULT_RATE,/* obsolete, do not use */ + + TCA_FQ_FLOW_MAX_RATE, /* per flow max rate */ + + TCA_FQ_BUCKETS_LOG, /* log2(number of buckets) */ ++ ++ TCA_FQ_FLOW_REFILL_DELAY, /* flow credit refill delay in usec */ ++ + __TCA_FQ_MAX + }; + +diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c +index bb22151..af8d1d4 100644 +--- a/kernel/time/ntp.c ++++ b/kernel/time/ntp.c +@@ -475,6 +475,7 @@ static void sync_cmos_clock(struct work_struct *work) + * called as close as possible to 500 ms before the new second starts. + * This code is run on a timer. If the clock is set, that timer + * may not expire at the correct time. Thus, we adjust... ++ * We want the clock to be within a couple of ticks from the target. + */ + if (!ntp_synced()) { + /* +@@ -485,7 +486,7 @@ static void sync_cmos_clock(struct work_struct *work) + } + + getnstimeofday(&now); +- if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) { ++ if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec * 5) { + struct timespec adjust = now; + + fail = -ENODEV; +diff --git a/lib/random32.c b/lib/random32.c +index 52280d5..01e8890 100644 +--- a/lib/random32.c ++++ b/lib/random32.c +@@ -141,7 +141,7 @@ void prandom_seed(u32 entropy) + */ + for_each_possible_cpu (i) { + struct rnd_state *state = &per_cpu(net_rand_state, i); +- state->s1 = __seed(state->s1 ^ entropy, 1); ++ state->s1 = __seed(state->s1 ^ entropy, 2); + } + } + EXPORT_SYMBOL(prandom_seed); +@@ -158,9 +158,9 @@ static int __init prandom_init(void) + struct rnd_state *state = &per_cpu(net_rand_state,i); + + #define LCG(x) ((x) * 69069) /* super-duper LCG */ +- state->s1 = __seed(LCG(i + jiffies), 1); +- state->s2 = __seed(LCG(state->s1), 7); +- state->s3 = __seed(LCG(state->s2), 15); ++ state->s1 = __seed(LCG(i + jiffies), 2); ++ state->s2 = __seed(LCG(state->s1), 8); ++ state->s3 = __seed(LCG(state->s2), 16); + + /* "warm it up" */ + prandom_u32_state(state); +@@ -187,9 +187,9 @@ static int __init prandom_reseed(void) + u32 seeds[3]; + + get_random_bytes(&seeds, sizeof(seeds)); +- state->s1 = __seed(seeds[0], 1); +- state->s2 = __seed(seeds[1], 7); +- state->s3 = __seed(seeds[2], 15); ++ state->s1 = __seed(seeds[0], 2); ++ state->s2 = __seed(seeds[1], 8); ++ state->s3 = __seed(seeds[2], 16); + + /* mix it in */ + prandom_u32_state(state); +diff --git a/mm/mprotect.c b/mm/mprotect.c +index 412ba2b..6c3f56f 100644 +--- a/mm/mprotect.c ++++ b/mm/mprotect.c +@@ -138,6 +138,7 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma, + pmd_t *pmd; + unsigned long next; + unsigned long pages = 0; ++ unsigned long nr_huge_updates = 0; + bool all_same_node; + + pmd = pmd_offset(pud, addr); +@@ -148,7 +149,8 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma, + split_huge_page_pmd(vma, addr, pmd); + else if (change_huge_pmd(vma, pmd, addr, newprot, + prot_numa)) { +- pages++; ++ pages += HPAGE_PMD_NR; ++ nr_huge_updates++; + continue; + } + /* fall through */ +@@ -168,6 +170,9 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma, + change_pmd_protnuma(vma->vm_mm, addr, pmd); + } while (pmd++, addr = next, addr != end); + ++ if (nr_huge_updates) ++ count_vm_numa_events(NUMA_HUGE_PTE_UPDATES, nr_huge_updates); ++ + return pages; + } + +diff --git a/mm/vmstat.c b/mm/vmstat.c +index 9bb3145..5a442a7 100644 +--- a/mm/vmstat.c ++++ b/mm/vmstat.c +@@ -812,6 +812,7 @@ const char * const vmstat_text[] = { + + #ifdef CONFIG_NUMA_BALANCING + "numa_pte_updates", ++ "numa_huge_pte_updates", + "numa_hint_faults", + "numa_hint_faults_local", + "numa_pages_migrated", +diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c +index 7fee50d..7d424ac 100644 +--- a/net/appletalk/ddp.c ++++ b/net/appletalk/ddp.c +@@ -1735,7 +1735,6 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr + size_t size, int flags) + { + struct sock *sk = sock->sk; +- struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name; + struct ddpehdr *ddp; + int copied = 0; + int offset = 0; +@@ -1764,14 +1763,13 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr + } + err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copied); + +- if (!err) { +- if (sat) { +- sat->sat_family = AF_APPLETALK; +- sat->sat_port = ddp->deh_sport; +- sat->sat_addr.s_node = ddp->deh_snode; +- sat->sat_addr.s_net = ddp->deh_snet; +- } +- msg->msg_namelen = sizeof(*sat); ++ if (!err && msg->msg_name) { ++ struct sockaddr_at *sat = msg->msg_name; ++ sat->sat_family = AF_APPLETALK; ++ sat->sat_port = ddp->deh_sport; ++ sat->sat_addr.s_node = ddp->deh_snode; ++ sat->sat_addr.s_net = ddp->deh_snet; ++ msg->msg_namelen = sizeof(*sat); + } + + skb_free_datagram(sk, skb); /* Free the datagram. */ +diff --git a/net/atm/common.c b/net/atm/common.c +index 737bef5..7b49100 100644 +--- a/net/atm/common.c ++++ b/net/atm/common.c +@@ -531,8 +531,6 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, + struct sk_buff *skb; + int copied, error = -EINVAL; + +- msg->msg_namelen = 0; +- + if (sock->state != SS_CONNECTED) + return -ENOTCONN; + +diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c +index 4b4d2b7..78c474f 100644 +--- a/net/ax25/af_ax25.c ++++ b/net/ax25/af_ax25.c +@@ -1636,11 +1636,11 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock, + + skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + +- if (msg->msg_namelen != 0) { +- struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name; ++ if (msg->msg_name) { + ax25_digi digi; + ax25_address src; + const unsigned char *mac = skb_mac_header(skb); ++ struct sockaddr_ax25 *sax = msg->msg_name; + + memset(sax, 0, sizeof(struct full_sockaddr_ax25)); + ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL, +diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c +index 9096137..6629cdc 100644 +--- a/net/bluetooth/af_bluetooth.c ++++ b/net/bluetooth/af_bluetooth.c +@@ -221,8 +221,6 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + if (flags & (MSG_OOB)) + return -EOPNOTSUPP; + +- msg->msg_namelen = 0; +- + skb = skb_recv_datagram(sk, flags, noblock, &err); + if (!skb) { + if (sk->sk_shutdown & RCV_SHUTDOWN) +@@ -287,8 +285,6 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, + if (flags & MSG_OOB) + return -EOPNOTSUPP; + +- msg->msg_namelen = 0; +- + BT_DBG("sk %p size %zu", sk, size); + + lock_sock(sk); +diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c +index 9bd7d95..fa4bf66 100644 +--- a/net/bluetooth/hci_sock.c ++++ b/net/bluetooth/hci_sock.c +@@ -752,8 +752,6 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + if (!skb) + return err; + +- msg->msg_namelen = 0; +- + copied = skb->len; + if (len < copied) { + msg->msg_flags |= MSG_TRUNC; +diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c +index 30b3721..c1c6028 100644 +--- a/net/bluetooth/rfcomm/sock.c ++++ b/net/bluetooth/rfcomm/sock.c +@@ -608,7 +608,6 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + + if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { + rfcomm_dlc_accept(d); +- msg->msg_namelen = 0; + return 0; + } + +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index 96bd388..d021e44 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -715,7 +715,6 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { + sco_conn_defer_accept(pi->conn->hcon, pi->setting); + sk->sk_state = BT_CONFIG; +- msg->msg_namelen = 0; + + release_sock(sk); + return 0; +diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c +index c41d5fb..547504c 100644 +--- a/net/bridge/br_if.c ++++ b/net/bridge/br_if.c +@@ -172,6 +172,8 @@ void br_dev_delete(struct net_device *dev, struct list_head *head) + del_nbp(p); + } + ++ br_fdb_delete_by_port(br, NULL, 1); ++ + del_timer_sync(&br->gc_timer); + + br_sysfs_delbr(br->dev); +diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c +index 05a41c7..d6be3ed 100644 +--- a/net/caif/caif_socket.c ++++ b/net/caif/caif_socket.c +@@ -286,8 +286,6 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock, + if (m->msg_flags&MSG_OOB) + goto read_error; + +- m->msg_namelen = 0; +- + skb = skb_recv_datagram(sk, flags, 0 , &ret); + if (!skb) + goto read_error; +@@ -361,8 +359,6 @@ static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock, + if (flags&MSG_OOB) + goto out; + +- msg->msg_namelen = 0; +- + /* + * Lock the socket to prevent queue disordering + * while sleeps in memcpy_tomsg +diff --git a/net/compat.c b/net/compat.c +index 8903258..dd32e34 100644 +--- a/net/compat.c ++++ b/net/compat.c +@@ -72,7 +72,7 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg) + __get_user(kmsg->msg_flags, &umsg->msg_flags)) + return -EFAULT; + if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) +- return -EINVAL; ++ kmsg->msg_namelen = sizeof(struct sockaddr_storage); + kmsg->msg_name = compat_ptr(tmp1); + kmsg->msg_iov = compat_ptr(tmp2); + kmsg->msg_control = compat_ptr(tmp3); +@@ -93,7 +93,8 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, + if (err < 0) + return err; + } +- kern_msg->msg_name = kern_address; ++ if (kern_msg->msg_name) ++ kern_msg->msg_name = kern_address; + } else + kern_msg->msg_name = NULL; + +diff --git a/net/core/dev.c b/net/core/dev.c +index 3430b1e..3d13874 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -1691,13 +1691,9 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) + kfree_skb(skb); + return NET_RX_DROP; + } +- skb->protocol = eth_type_trans(skb, dev); + +- /* eth_type_trans() can set pkt_type. +- * call skb_scrub_packet() after it to clear pkt_type _after_ calling +- * eth_type_trans(). +- */ + skb_scrub_packet(skb, true); ++ skb->protocol = eth_type_trans(skb, dev); + + return netif_rx(skb); + } +@@ -4819,7 +4815,7 @@ static void dev_change_rx_flags(struct net_device *dev, int flags) + { + const struct net_device_ops *ops = dev->netdev_ops; + +- if ((dev->flags & IFF_UP) && ops->ndo_change_rx_flags) ++ if (ops->ndo_change_rx_flags) + ops->ndo_change_rx_flags(dev, flags); + } + +diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c +index 2e65413..f409e0b 100644 +--- a/net/core/fib_rules.c ++++ b/net/core/fib_rules.c +@@ -460,7 +460,8 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh) + if (frh->action && (frh->action != rule->action)) + continue; + +- if (frh->table && (frh_get_table(frh, tb) != rule->table)) ++ if (frh_get_table(frh, tb) && ++ (frh_get_table(frh, tb) != rule->table)) + continue; + + if (tb[FRA_PRIORITY] && +diff --git a/net/core/iovec.c b/net/core/iovec.c +index b77eeec..7d84ea1 100644 +--- a/net/core/iovec.c ++++ b/net/core/iovec.c +@@ -48,7 +48,8 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a + if (err < 0) + return err; + } +- m->msg_name = address; ++ if (m->msg_name) ++ m->msg_name = address; + } else { + m->msg_name = NULL; + } +diff --git a/net/core/pktgen.c b/net/core/pktgen.c +index 261357a..a797fff 100644 +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -2527,6 +2527,8 @@ static int process_ipsec(struct pktgen_dev *pkt_dev, + if (x) { + int ret; + __u8 *eth; ++ struct iphdr *iph; ++ + nhead = x->props.header_len - skb_headroom(skb); + if (nhead > 0) { + ret = pskb_expand_head(skb, nhead, 0, GFP_ATOMIC); +@@ -2548,6 +2550,11 @@ static int process_ipsec(struct pktgen_dev *pkt_dev, + eth = (__u8 *) skb_push(skb, ETH_HLEN); + memcpy(eth, pkt_dev->hh, 12); + *(u16 *) ð[12] = protocol; ++ ++ /* Update IPv4 header len as well as checksum value */ ++ iph = ip_hdr(skb); ++ iph->tot_len = htons(skb->len - ETH_HLEN); ++ ip_send_check(iph); + } + } + return 1; +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index d81cff1..c28c7fe 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -580,9 +580,6 @@ static void skb_release_head_state(struct sk_buff *skb) + #if IS_ENABLED(CONFIG_NF_CONNTRACK) + nf_conntrack_put(skb->nfct); + #endif +-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED +- nf_conntrack_put_reasm(skb->nfct_reasm); +-#endif + #ifdef CONFIG_BRIDGE_NETFILTER + nf_bridge_put(skb->nf_bridge); + #endif +@@ -2758,6 +2755,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) + struct sk_buff *segs = NULL; + struct sk_buff *tail = NULL; + struct sk_buff *fskb = skb_shinfo(skb)->frag_list; ++ skb_frag_t *skb_frag = skb_shinfo(skb)->frags; + unsigned int mss = skb_shinfo(skb)->gso_size; + unsigned int doffset = skb->data - skb_mac_header(skb); + unsigned int offset = doffset; +@@ -2797,16 +2795,38 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) + if (hsize > len || !sg) + hsize = len; + +- if (!hsize && i >= nfrags) { +- BUG_ON(fskb->len != len); ++ if (!hsize && i >= nfrags && skb_headlen(fskb) && ++ (skb_headlen(fskb) == len || sg)) { ++ BUG_ON(skb_headlen(fskb) > len); ++ ++ i = 0; ++ nfrags = skb_shinfo(fskb)->nr_frags; ++ skb_frag = skb_shinfo(fskb)->frags; ++ pos += skb_headlen(fskb); ++ ++ while (pos < offset + len) { ++ BUG_ON(i >= nfrags); ++ ++ size = skb_frag_size(skb_frag); ++ if (pos + size > offset + len) ++ break; ++ ++ i++; ++ pos += size; ++ skb_frag++; ++ } + +- pos += len; + nskb = skb_clone(fskb, GFP_ATOMIC); + fskb = fskb->next; + + if (unlikely(!nskb)) + goto err; + ++ if (unlikely(pskb_trim(nskb, len))) { ++ kfree_skb(nskb); ++ goto err; ++ } ++ + hsize = skb_end_offset(nskb); + if (skb_cow_head(nskb, doffset + headroom)) { + kfree_skb(nskb); +@@ -2850,7 +2870,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) + nskb->data - tnl_hlen, + doffset + tnl_hlen); + +- if (fskb != skb_shinfo(skb)->frag_list) ++ if (nskb->len == len + doffset) + goto perform_csum_check; + + if (!sg) { +@@ -2868,8 +2888,28 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) + + skb_shinfo(nskb)->tx_flags = skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG; + +- while (pos < offset + len && i < nfrags) { +- *frag = skb_shinfo(skb)->frags[i]; ++ while (pos < offset + len) { ++ if (i >= nfrags) { ++ BUG_ON(skb_headlen(fskb)); ++ ++ i = 0; ++ nfrags = skb_shinfo(fskb)->nr_frags; ++ skb_frag = skb_shinfo(fskb)->frags; ++ ++ BUG_ON(!nfrags); ++ ++ fskb = fskb->next; ++ } ++ ++ if (unlikely(skb_shinfo(nskb)->nr_frags >= ++ MAX_SKB_FRAGS)) { ++ net_warn_ratelimited( ++ "skb_segment: too many frags: %u %u\n", ++ pos, mss); ++ goto err; ++ } ++ ++ *frag = *skb_frag; + __skb_frag_ref(frag); + size = skb_frag_size(frag); + +@@ -2882,6 +2922,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) + + if (pos + size <= offset + len) { + i++; ++ skb_frag++; + pos += size; + } else { + skb_frag_size_sub(frag, pos + size - (offset + len)); +@@ -2891,25 +2932,6 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) + frag++; + } + +- if (pos < offset + len) { +- struct sk_buff *fskb2 = fskb; +- +- BUG_ON(pos + fskb->len != offset + len); +- +- pos += fskb->len; +- fskb = fskb->next; +- +- if (fskb2->next) { +- fskb2 = skb_clone(fskb2, GFP_ATOMIC); +- if (!fskb2) +- goto err; +- } else +- skb_get(fskb2); +- +- SKB_FRAG_ASSERT(nskb); +- skb_shinfo(nskb)->frag_list = fskb2; +- } +- + skip_fraglist: + nskb->data_len = len - hsize; + nskb->len += nskb->data_len; +diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c +index ff41b4d..008f337 100644 +--- a/net/ieee802154/6lowpan.c ++++ b/net/ieee802154/6lowpan.c +@@ -957,7 +957,7 @@ lowpan_process_data(struct sk_buff *skb) + * Traffic class carried in-line + * ECN + DSCP (1 byte), Flow Label is elided + */ +- case 1: /* 10b */ ++ case 2: /* 10b */ + if (lowpan_fetch_skb_u8(skb, &tmp)) + goto drop; + +@@ -968,7 +968,7 @@ lowpan_process_data(struct sk_buff *skb) + * Flow Label carried in-line + * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided + */ +- case 2: /* 01b */ ++ case 1: /* 01b */ + if (lowpan_fetch_skb_u8(skb, &tmp)) + goto drop; + +diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c +index 581a595..1865fdf 100644 +--- a/net/ieee802154/dgram.c ++++ b/net/ieee802154/dgram.c +@@ -315,9 +315,8 @@ static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk, + if (saddr) { + saddr->family = AF_IEEE802154; + saddr->addr = mac_cb(skb)->sa; +- } +- if (addr_len) + *addr_len = sizeof(*saddr); ++ } + + if (flags & MSG_TRUNC) + copied = skb->len; +diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c +index b28e863..19e3637 100644 +--- a/net/ipv4/datagram.c ++++ b/net/ipv4/datagram.c +@@ -57,7 +57,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) + if (IS_ERR(rt)) { + err = PTR_ERR(rt); + if (err == -ENETUNREACH) +- IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); ++ IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); + goto out; + } + +diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c +index d9c4f11..23e6ab0 100644 +--- a/net/ipv4/ip_sockglue.c ++++ b/net/ipv4/ip_sockglue.c +@@ -368,7 +368,7 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 inf + /* + * Handle MSG_ERRQUEUE + */ +-int ip_recv_error(struct sock *sk, struct msghdr *msg, int len) ++int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) + { + struct sock_exterr_skb *serr; + struct sk_buff *skb, *skb2; +@@ -405,6 +405,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len) + serr->addr_offset); + sin->sin_port = serr->port; + memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); ++ *addr_len = sizeof(*sin); + } + + memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); +diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c +index 63a6d6d..254f11c 100644 +--- a/net/ipv4/ip_tunnel.c ++++ b/net/ipv4/ip_tunnel.c +@@ -454,6 +454,8 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, + tstats->rx_bytes += skb->len; + u64_stats_update_end(&tstats->syncp); + ++ skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(tunnel->dev))); ++ + if (tunnel->dev->type == ARPHRD_ETHER) { + skb->protocol = eth_type_trans(skb, tunnel->dev); + skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); +@@ -461,8 +463,6 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, + skb->dev = tunnel->dev; + } + +- skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(tunnel->dev))); +- + gro_cells_receive(&tunnel->gro_cells, skb); + return 0; + +diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c +index 6e87f85..26847e1 100644 +--- a/net/ipv4/ip_vti.c ++++ b/net/ipv4/ip_vti.c +@@ -190,6 +190,7 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) + if (!rt->dst.xfrm || + rt->dst.xfrm->props.mode != XFRM_MODE_TUNNEL) { + dev->stats.tx_carrier_errors++; ++ ip_rt_put(rt); + goto tx_error_icmp; + } + tdev = rt->dst.dev; +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index d7d9882..c482f7c 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -769,7 +769,7 @@ int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + err = PTR_ERR(rt); + rt = NULL; + if (err == -ENETUNREACH) +- IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); ++ IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES); + goto out; + } + +@@ -827,8 +827,6 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + { + struct inet_sock *isk = inet_sk(sk); + int family = sk->sk_family; +- struct sockaddr_in *sin; +- struct sockaddr_in6 *sin6; + struct sk_buff *skb; + int copied, err; + +@@ -838,19 +836,13 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + if (flags & MSG_OOB) + goto out; + +- if (addr_len) { +- if (family == AF_INET) +- *addr_len = sizeof(*sin); +- else if (family == AF_INET6 && addr_len) +- *addr_len = sizeof(*sin6); +- } +- + if (flags & MSG_ERRQUEUE) { + if (family == AF_INET) { +- return ip_recv_error(sk, msg, len); ++ return ip_recv_error(sk, msg, len, addr_len); + #if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { +- return pingv6_ops.ipv6_recv_error(sk, msg, len); ++ return pingv6_ops.ipv6_recv_error(sk, msg, len, ++ addr_len); + #endif + } + } +@@ -874,11 +866,15 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + + /* Copy the address and add cmsg data. */ + if (family == AF_INET) { +- sin = (struct sockaddr_in *) msg->msg_name; +- sin->sin_family = AF_INET; +- sin->sin_port = 0 /* skb->h.uh->source */; +- sin->sin_addr.s_addr = ip_hdr(skb)->saddr; +- memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); ++ struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; ++ ++ if (sin) { ++ sin->sin_family = AF_INET; ++ sin->sin_port = 0 /* skb->h.uh->source */; ++ sin->sin_addr.s_addr = ip_hdr(skb)->saddr; ++ memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); ++ *addr_len = sizeof(*sin); ++ } + + if (isk->cmsg_flags) + ip_cmsg_recv(msg, skb); +@@ -887,17 +883,21 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + } else if (family == AF_INET6) { + struct ipv6_pinfo *np = inet6_sk(sk); + struct ipv6hdr *ip6 = ipv6_hdr(skb); +- sin6 = (struct sockaddr_in6 *) msg->msg_name; +- sin6->sin6_family = AF_INET6; +- sin6->sin6_port = 0; +- sin6->sin6_addr = ip6->saddr; +- +- sin6->sin6_flowinfo = 0; +- if (np->sndflow) +- sin6->sin6_flowinfo = ip6_flowinfo(ip6); +- +- sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr, +- IP6CB(skb)->iif); ++ struct sockaddr_in6 *sin6 = ++ (struct sockaddr_in6 *)msg->msg_name; ++ ++ if (sin6) { ++ sin6->sin6_family = AF_INET6; ++ sin6->sin6_port = 0; ++ sin6->sin6_addr = ip6->saddr; ++ sin6->sin6_flowinfo = 0; ++ if (np->sndflow) ++ sin6->sin6_flowinfo = ip6_flowinfo(ip6); ++ sin6->sin6_scope_id = ++ ipv6_iface_scope_id(&sin6->sin6_addr, ++ IP6CB(skb)->iif); ++ *addr_len = sizeof(*sin6); ++ } + + if (inet6_sk(sk)->rxopt.all) + pingv6_ops.ip6_datagram_recv_ctl(sk, msg, skb); +diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c +index 193db03..7d3db78 100644 +--- a/net/ipv4/raw.c ++++ b/net/ipv4/raw.c +@@ -694,11 +694,8 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + if (flags & MSG_OOB) + goto out; + +- if (addr_len) +- *addr_len = sizeof(*sin); +- + if (flags & MSG_ERRQUEUE) { +- err = ip_recv_error(sk, msg, len); ++ err = ip_recv_error(sk, msg, len, addr_len); + goto out; + } + +@@ -724,6 +721,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + sin->sin_addr.s_addr = ip_hdr(skb)->saddr; + sin->sin_port = 0; + memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); ++ *addr_len = sizeof(*sin); + } + if (inet->cmsg_flags) + ip_cmsg_recv(msg, skb); +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 6011615..62290b5 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -1772,8 +1772,12 @@ local_input: + rth->dst.error= -err; + rth->rt_flags &= ~RTCF_LOCAL; + } +- if (do_cache) +- rt_cache_route(&FIB_RES_NH(res), rth); ++ if (do_cache) { ++ if (unlikely(!rt_cache_route(&FIB_RES_NH(res), rth))) { ++ rth->dst.flags |= DST_NOCACHE; ++ rt_add_uncached_list(rth); ++ } ++ } + skb_dst_set(skb, &rth->dst); + err = 0; + goto out; +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 6e5617b..be5246e 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -806,12 +806,6 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, + xmit_size_goal = min_t(u32, gso_size, + sk->sk_gso_max_size - 1 - hlen); + +- /* TSQ : try to have at least two segments in flight +- * (one in NIC TX ring, another in Qdisc) +- */ +- xmit_size_goal = min_t(u32, xmit_size_goal, +- sysctl_tcp_limit_output_bytes >> 1); +- + xmit_size_goal = tcp_bound_to_half_wnd(tp, xmit_size_goal); + + /* We try hard to avoid divides here */ +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index b14266b..5031f68 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -177,7 +177,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) + if (IS_ERR(rt)) { + err = PTR_ERR(rt); + if (err == -ENETUNREACH) +- IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); ++ IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); + return err; + } + +diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c +index 52f3c6b..3107114 100644 +--- a/net/ipv4/tcp_metrics.c ++++ b/net/ipv4/tcp_metrics.c +@@ -659,10 +659,13 @@ void tcp_fastopen_cache_get(struct sock *sk, u16 *mss, + void tcp_fastopen_cache_set(struct sock *sk, u16 mss, + struct tcp_fastopen_cookie *cookie, bool syn_lost) + { ++ struct dst_entry *dst = __sk_dst_get(sk); + struct tcp_metrics_block *tm; + ++ if (!dst) ++ return; + rcu_read_lock(); +- tm = tcp_get_metrics(sk, __sk_dst_get(sk), true); ++ tm = tcp_get_metrics(sk, dst, true); + if (tm) { + struct tcp_fastopen_metrics *tfom = &tm->tcpm_fastopen; + +diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c +index 533c58a..910ab81 100644 +--- a/net/ipv4/tcp_offload.c ++++ b/net/ipv4/tcp_offload.c +@@ -272,33 +272,32 @@ static struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff * + { + const struct iphdr *iph = skb_gro_network_header(skb); + __wsum wsum; +- __sum16 sum; ++ ++ /* Don't bother verifying checksum if we're going to flush anyway. */ ++ if (NAPI_GRO_CB(skb)->flush) ++ goto skip_csum; ++ ++ wsum = skb->csum; + + switch (skb->ip_summed) { ++ case CHECKSUM_NONE: ++ wsum = skb_checksum(skb, skb_gro_offset(skb), skb_gro_len(skb), ++ 0); ++ ++ /* fall through */ ++ + case CHECKSUM_COMPLETE: + if (!tcp_v4_check(skb_gro_len(skb), iph->saddr, iph->daddr, +- skb->csum)) { ++ wsum)) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + break; + } +-flush: ++ + NAPI_GRO_CB(skb)->flush = 1; + return NULL; +- +- case CHECKSUM_NONE: +- wsum = csum_tcpudp_nofold(iph->saddr, iph->daddr, +- skb_gro_len(skb), IPPROTO_TCP, 0); +- sum = csum_fold(skb_checksum(skb, +- skb_gro_offset(skb), +- skb_gro_len(skb), +- wsum)); +- if (sum) +- goto flush; +- +- skb->ip_summed = CHECKSUM_UNNECESSARY; +- break; + } + ++skip_csum: + return tcp_gro_receive(head, skb); + } + +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index d46f214..e912634 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -1875,8 +1875,12 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, + * - better RTT estimation and ACK scheduling + * - faster recovery + * - high rates ++ * Alas, some drivers / subsystems require a fair amount ++ * of queued bytes to ensure line rate. ++ * One example is wifi aggregation (802.11 AMPDU) + */ +- limit = max(skb->truesize, sk->sk_pacing_rate >> 10); ++ limit = max_t(unsigned int, sysctl_tcp_limit_output_bytes, ++ sk->sk_pacing_rate >> 10); + + if (atomic_read(&sk->sk_wmem_alloc) > limit) { + set_bit(TSQ_THROTTLED, &tp->tsq_flags); +@@ -3108,7 +3112,6 @@ void tcp_send_window_probe(struct sock *sk) + { + if (sk->sk_state == TCP_ESTABLISHED) { + tcp_sk(sk)->snd_wl1 = tcp_sk(sk)->rcv_nxt - 1; +- tcp_sk(sk)->snd_nxt = tcp_sk(sk)->write_seq; + tcp_xmit_probe_skb(sk, 0); + } + } +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 0ca44df..5e2c2f1 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -973,7 +973,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + err = PTR_ERR(rt); + rt = NULL; + if (err == -ENETUNREACH) +- IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); ++ IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES); + goto out; + } + +@@ -1072,6 +1072,9 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset, + struct udp_sock *up = udp_sk(sk); + int ret; + ++ if (flags & MSG_SENDPAGE_NOTLAST) ++ flags |= MSG_MORE; ++ + if (!up->pending) { + struct msghdr msg = { .msg_flags = flags|MSG_MORE }; + +@@ -1209,14 +1212,8 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + int is_udplite = IS_UDPLITE(sk); + bool slow; + +- /* +- * Check any passed addresses +- */ +- if (addr_len) +- *addr_len = sizeof(*sin); +- + if (flags & MSG_ERRQUEUE) +- return ip_recv_error(sk, msg, len); ++ return ip_recv_error(sk, msg, len, addr_len); + + try_again: + skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), +@@ -1276,6 +1273,7 @@ try_again: + sin->sin_port = udp_hdr(skb)->source; + sin->sin_addr.s_addr = ip_hdr(skb)->saddr; + memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); ++ *addr_len = sizeof(*sin); + } + if (inet->cmsg_flags) + ip_cmsg_recv(msg, skb); +diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c +index ccde542..adf9983 100644 +--- a/net/ipv4/xfrm4_policy.c ++++ b/net/ipv4/xfrm4_policy.c +@@ -104,10 +104,14 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) + const struct iphdr *iph = ip_hdr(skb); + u8 *xprth = skb_network_header(skb) + iph->ihl * 4; + struct flowi4 *fl4 = &fl->u.ip4; ++ int oif = 0; ++ ++ if (skb_dst(skb)) ++ oif = skb_dst(skb)->dev->ifindex; + + memset(fl4, 0, sizeof(struct flowi4)); + fl4->flowi4_mark = skb->mark; +- fl4->flowi4_oif = skb_dst(skb)->dev->ifindex; ++ fl4->flowi4_oif = reverse ? skb->skb_iif : oif; + + if (!ip_is_fragment(iph)) { + switch (iph->protocol) { +diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c +index 7c96100..8132b44 100644 +--- a/net/ipv6/af_inet6.c ++++ b/net/ipv6/af_inet6.c +@@ -965,10 +965,10 @@ out: + + #ifdef CONFIG_SYSCTL + sysctl_fail: +- ipv6_packet_cleanup(); ++ pingv6_exit(); + #endif + pingv6_fail: +- pingv6_exit(); ++ ipv6_packet_cleanup(); + ipv6_packet_fail: + tcpv6_exit(); + tcpv6_fail: +diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c +index 48b6bd2..c66c6df 100644 +--- a/net/ipv6/datagram.c ++++ b/net/ipv6/datagram.c +@@ -318,7 +318,7 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu) + /* + * Handle MSG_ERRQUEUE + */ +-int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) ++int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) + { + struct ipv6_pinfo *np = inet6_sk(sk); + struct sock_exterr_skb *serr; +@@ -369,6 +369,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) + &sin->sin6_addr); + sin->sin6_scope_id = 0; + } ++ *addr_len = sizeof(*sin); + } + + memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); +@@ -377,6 +378,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) + if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { + sin->sin6_family = AF_INET6; + sin->sin6_flowinfo = 0; ++ sin->sin6_port = 0; + if (skb->protocol == htons(ETH_P_IPV6)) { + sin->sin6_addr = ipv6_hdr(skb)->saddr; + if (np->rxopt.all) +@@ -423,7 +425,8 @@ EXPORT_SYMBOL_GPL(ipv6_recv_error); + /* + * Handle IPV6_RECVPATHMTU + */ +-int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len) ++int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len, ++ int *addr_len) + { + struct ipv6_pinfo *np = inet6_sk(sk); + struct sk_buff *skb; +@@ -457,6 +460,7 @@ int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len) + sin->sin6_port = 0; + sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id; + sin->sin6_addr = mtu_info.ip6m_addr.sin6_addr; ++ *addr_len = sizeof(*sin); + } + + put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info); +diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c +index 46e8843..f0ccdb7 100644 +--- a/net/ipv6/ip6_flowlabel.c ++++ b/net/ipv6/ip6_flowlabel.c +@@ -453,8 +453,10 @@ static int mem_check(struct sock *sk) + if (room > FL_MAX_SIZE - FL_MAX_PER_SOCK) + return 0; + ++ rcu_read_lock_bh(); + for_each_sk_fl_rcu(np, sfl) + count++; ++ rcu_read_unlock_bh(); + + if (room <= 0 || + ((count >= FL_MAX_PER_SOCK || +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 91fb4e8..b6fa35e 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -116,8 +116,8 @@ static int ip6_finish_output2(struct sk_buff *skb) + } + rcu_read_unlock_bh(); + +- IP6_INC_STATS_BH(dev_net(dst->dev), +- ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); ++ IP6_INC_STATS(dev_net(dst->dev), ++ ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); + kfree_skb(skb); + return -EINVAL; + } +@@ -125,7 +125,8 @@ static int ip6_finish_output2(struct sk_buff *skb) + static int ip6_finish_output(struct sk_buff *skb) + { + if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || +- dst_allfrag(skb_dst(skb))) ++ dst_allfrag(skb_dst(skb)) || ++ (IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size)) + return ip6_fragment(skb, ip6_finish_output2); + else + return ip6_finish_output2(skb); +diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c +index 583b77e..c1e11b5 100644 +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -1635,6 +1635,15 @@ static int ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[], + return ip6_tnl_update(t, &p); + } + ++static void ip6_tnl_dellink(struct net_device *dev, struct list_head *head) ++{ ++ struct net *net = dev_net(dev); ++ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); ++ ++ if (dev != ip6n->fb_tnl_dev) ++ unregister_netdevice_queue(dev, head); ++} ++ + static size_t ip6_tnl_get_size(const struct net_device *dev) + { + return +@@ -1699,6 +1708,7 @@ static struct rtnl_link_ops ip6_link_ops __read_mostly = { + .validate = ip6_tnl_validate, + .newlink = ip6_tnl_newlink, + .changelink = ip6_tnl_changelink, ++ .dellink = ip6_tnl_dellink, + .get_size = ip6_tnl_get_size, + .fill_info = ip6_tnl_fill_info, + }; +@@ -1715,9 +1725,9 @@ static struct xfrm6_tunnel ip6ip6_handler __read_mostly = { + .priority = 1, + }; + +-static void __net_exit ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) ++static void __net_exit ip6_tnl_destroy_tunnels(struct net *net) + { +- struct net *net = dev_net(ip6n->fb_tnl_dev); ++ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + struct net_device *dev, *aux; + int h; + struct ip6_tnl *t; +@@ -1785,10 +1795,8 @@ err_alloc_dev: + + static void __net_exit ip6_tnl_exit_net(struct net *net) + { +- struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); +- + rtnl_lock(); +- ip6_tnl_destroy_tunnels(ip6n); ++ ip6_tnl_destroy_tunnels(net); + rtnl_unlock(); + } + +diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +index d6e4dd8..83ab37c 100644 +--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c ++++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +@@ -169,63 +169,13 @@ out: + return nf_conntrack_confirm(skb); + } + +-static unsigned int __ipv6_conntrack_in(struct net *net, +- unsigned int hooknum, +- struct sk_buff *skb, +- const struct net_device *in, +- const struct net_device *out, +- int (*okfn)(struct sk_buff *)) +-{ +- struct sk_buff *reasm = skb->nfct_reasm; +- const struct nf_conn_help *help; +- struct nf_conn *ct; +- enum ip_conntrack_info ctinfo; +- +- /* This packet is fragmented and has reassembled packet. */ +- if (reasm) { +- /* Reassembled packet isn't parsed yet ? */ +- if (!reasm->nfct) { +- unsigned int ret; +- +- ret = nf_conntrack_in(net, PF_INET6, hooknum, reasm); +- if (ret != NF_ACCEPT) +- return ret; +- } +- +- /* Conntrack helpers need the entire reassembled packet in the +- * POST_ROUTING hook. In case of unconfirmed connections NAT +- * might reassign a helper, so the entire packet is also +- * required. +- */ +- ct = nf_ct_get(reasm, &ctinfo); +- if (ct != NULL && !nf_ct_is_untracked(ct)) { +- help = nfct_help(ct); +- if ((help && help->helper) || !nf_ct_is_confirmed(ct)) { +- nf_conntrack_get_reasm(reasm); +- NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, reasm, +- (struct net_device *)in, +- (struct net_device *)out, +- okfn, NF_IP6_PRI_CONNTRACK + 1); +- return NF_DROP_ERR(-ECANCELED); +- } +- } +- +- nf_conntrack_get(reasm->nfct); +- skb->nfct = reasm->nfct; +- skb->nfctinfo = reasm->nfctinfo; +- return NF_ACCEPT; +- } +- +- return nf_conntrack_in(net, PF_INET6, hooknum, skb); +-} +- + static unsigned int ipv6_conntrack_in(unsigned int hooknum, + struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) + { +- return __ipv6_conntrack_in(dev_net(in), hooknum, skb, in, out, okfn); ++ return nf_conntrack_in(dev_net(in), PF_INET6, hooknum, skb); + } + + static unsigned int ipv6_conntrack_local(unsigned int hooknum, +@@ -239,7 +189,7 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum, + net_notice_ratelimited("ipv6_conntrack_local: packet too short\n"); + return NF_ACCEPT; + } +- return __ipv6_conntrack_in(dev_net(out), hooknum, skb, in, out, okfn); ++ return nf_conntrack_in(dev_net(out), PF_INET6, hooknum, skb); + } + + static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = { +diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c +index dffdc1a..253566a 100644 +--- a/net/ipv6/netfilter/nf_conntrack_reasm.c ++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c +@@ -621,31 +621,16 @@ ret_orig: + return skb; + } + +-void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, +- struct net_device *in, struct net_device *out, +- int (*okfn)(struct sk_buff *)) ++void nf_ct_frag6_consume_orig(struct sk_buff *skb) + { + struct sk_buff *s, *s2; +- unsigned int ret = 0; + + for (s = NFCT_FRAG6_CB(skb)->orig; s;) { +- nf_conntrack_put_reasm(s->nfct_reasm); +- nf_conntrack_get_reasm(skb); +- s->nfct_reasm = skb; +- + s2 = s->next; + s->next = NULL; +- +- if (ret != -ECANCELED) +- ret = NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, s, +- in, out, okfn, +- NF_IP6_PRI_CONNTRACK_DEFRAG + 1); +- else +- kfree_skb(s); +- ++ consume_skb(s); + s = s2; + } +- nf_conntrack_put_reasm(skb); + } + + static int nf_ct_net_init(struct net *net) +diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +index aacd121..581dd9e 100644 +--- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c ++++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +@@ -75,8 +75,11 @@ static unsigned int ipv6_defrag(unsigned int hooknum, + if (reasm == skb) + return NF_ACCEPT; + +- nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in, +- (struct net_device *)out, okfn); ++ nf_ct_frag6_consume_orig(reasm); ++ ++ NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, reasm, ++ (struct net_device *) in, (struct net_device *) out, ++ okfn, NF_IP6_PRI_CONNTRACK_DEFRAG + 1); + + return NF_STOLEN; + } +diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c +index 18f19df..7856e96 100644 +--- a/net/ipv6/ping.c ++++ b/net/ipv6/ping.c +@@ -57,7 +57,8 @@ static struct inet_protosw pingv6_protosw = { + + + /* Compatibility glue so we can support IPv6 when it's compiled as a module */ +-static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) ++static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, ++ int *addr_len) + { + return -EAFNOSUPPORT; + } +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index a4ed241..430067c 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -466,14 +466,11 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, + if (flags & MSG_OOB) + return -EOPNOTSUPP; + +- if (addr_len) +- *addr_len=sizeof(*sin6); +- + if (flags & MSG_ERRQUEUE) +- return ipv6_recv_error(sk, msg, len); ++ return ipv6_recv_error(sk, msg, len, addr_len); + + if (np->rxpmtu && np->rxopt.bits.rxpmtu) +- return ipv6_recv_rxpmtu(sk, msg, len); ++ return ipv6_recv_rxpmtu(sk, msg, len, addr_len); + + skb = skb_recv_datagram(sk, flags, noblock, &err); + if (!skb) +@@ -507,6 +504,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, + sin6->sin6_flowinfo = 0; + sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr, + IP6CB(skb)->iif); ++ *addr_len = sizeof(*sin6); + } + + sock_recv_ts_and_drops(msg, sk, skb); +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 04e17b3..77308af 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -731,8 +731,11 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, + prefix = &prefix_buf; + } + +- rt = rt6_get_route_info(net, prefix, rinfo->prefix_len, gwaddr, +- dev->ifindex); ++ if (rinfo->prefix_len == 0) ++ rt = rt6_get_dflt_router(gwaddr, dev); ++ else ++ rt = rt6_get_route_info(net, prefix, rinfo->prefix_len, ++ gwaddr, dev->ifindex); + + if (rt && !lifetime) { + ip6_del_rt(rt); +diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c +index 1926945..b433884 100644 +--- a/net/ipv6/sit.c ++++ b/net/ipv6/sit.c +@@ -1594,6 +1594,15 @@ static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = { + #endif + }; + ++static void ipip6_dellink(struct net_device *dev, struct list_head *head) ++{ ++ struct net *net = dev_net(dev); ++ struct sit_net *sitn = net_generic(net, sit_net_id); ++ ++ if (dev != sitn->fb_tunnel_dev) ++ unregister_netdevice_queue(dev, head); ++} ++ + static struct rtnl_link_ops sit_link_ops __read_mostly = { + .kind = "sit", + .maxtype = IFLA_IPTUN_MAX, +@@ -1605,6 +1614,7 @@ static struct rtnl_link_ops sit_link_ops __read_mostly = { + .changelink = ipip6_changelink, + .get_size = ipip6_get_size, + .fill_info = ipip6_fill_info, ++ .dellink = ipip6_dellink, + }; + + static struct xfrm_tunnel sit_handler __read_mostly = { +@@ -1619,9 +1629,10 @@ static struct xfrm_tunnel ipip_handler __read_mostly = { + .priority = 2, + }; + +-static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head) ++static void __net_exit sit_destroy_tunnels(struct net *net, ++ struct list_head *head) + { +- struct net *net = dev_net(sitn->fb_tunnel_dev); ++ struct sit_net *sitn = net_generic(net, sit_net_id); + struct net_device *dev, *aux; + int prio; + +@@ -1696,11 +1707,10 @@ err_alloc_dev: + + static void __net_exit sit_exit_net(struct net *net) + { +- struct sit_net *sitn = net_generic(net, sit_net_id); + LIST_HEAD(list); + + rtnl_lock(); +- sit_destroy_tunnels(sitn, &list); ++ sit_destroy_tunnels(net, &list); + unregister_netdevice_many(&list); + rtnl_unlock(); + } +diff --git a/net/ipv6/tcpv6_offload.c b/net/ipv6/tcpv6_offload.c +index 2ec6bf6..a7a2384 100644 +--- a/net/ipv6/tcpv6_offload.c ++++ b/net/ipv6/tcpv6_offload.c +@@ -37,34 +37,32 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, + { + const struct ipv6hdr *iph = skb_gro_network_header(skb); + __wsum wsum; +- __sum16 sum; ++ ++ /* Don't bother verifying checksum if we're going to flush anyway. */ ++ if (NAPI_GRO_CB(skb)->flush) ++ goto skip_csum; ++ ++ wsum = skb->csum; + + switch (skb->ip_summed) { ++ case CHECKSUM_NONE: ++ wsum = skb_checksum(skb, skb_gro_offset(skb), skb_gro_len(skb), ++ wsum); ++ ++ /* fall through */ ++ + case CHECKSUM_COMPLETE: + if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr, +- skb->csum)) { ++ wsum)) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + break; + } +-flush: ++ + NAPI_GRO_CB(skb)->flush = 1; + return NULL; +- +- case CHECKSUM_NONE: +- wsum = ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr, +- skb_gro_len(skb), +- IPPROTO_TCP, 0)); +- sum = csum_fold(skb_checksum(skb, +- skb_gro_offset(skb), +- skb_gro_len(skb), +- wsum)); +- if (sum) +- goto flush; +- +- skb->ip_summed = CHECKSUM_UNNECESSARY; +- break; + } + ++skip_csum: + return tcp_gro_receive(head, skb); + } + +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 1878609..3d2758d 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -374,14 +374,11 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, + int is_udp4; + bool slow; + +- if (addr_len) +- *addr_len = sizeof(struct sockaddr_in6); +- + if (flags & MSG_ERRQUEUE) +- return ipv6_recv_error(sk, msg, len); ++ return ipv6_recv_error(sk, msg, len, addr_len); + + if (np->rxpmtu && np->rxopt.bits.rxpmtu) +- return ipv6_recv_rxpmtu(sk, msg, len); ++ return ipv6_recv_rxpmtu(sk, msg, len, addr_len); + + try_again: + skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), +@@ -462,7 +459,7 @@ try_again: + ipv6_iface_scope_id(&sin6->sin6_addr, + IP6CB(skb)->iif); + } +- ++ *addr_len = sizeof(*sin6); + } + if (is_udp4) { + if (inet->cmsg_flags) +diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c +index 6055951..34c6fff 100644 +--- a/net/ipv6/udp_offload.c ++++ b/net/ipv6/udp_offload.c +@@ -88,7 +88,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, + + /* Check if there is enough headroom to insert fragment header. */ + tnl_hlen = skb_tnl_header_len(skb); +- if (skb_headroom(skb) < (tnl_hlen + frag_hdr_sz)) { ++ if (skb->mac_header < (tnl_hlen + frag_hdr_sz)) { + if (gso_pskb_expand_head(skb, tnl_hlen + frag_hdr_sz)) + goto out; + } +diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c +index 08ed277..550b195 100644 +--- a/net/ipv6/xfrm6_policy.c ++++ b/net/ipv6/xfrm6_policy.c +@@ -135,10 +135,14 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) + struct ipv6_opt_hdr *exthdr; + const unsigned char *nh = skb_network_header(skb); + u8 nexthdr = nh[IP6CB(skb)->nhoff]; ++ int oif = 0; ++ ++ if (skb_dst(skb)) ++ oif = skb_dst(skb)->dev->ifindex; + + memset(fl6, 0, sizeof(struct flowi6)); + fl6->flowi6_mark = skb->mark; +- fl6->flowi6_oif = skb_dst(skb)->dev->ifindex; ++ fl6->flowi6_oif = reverse ? skb->skb_iif : oif; + + fl6->daddr = reverse ? hdr->saddr : hdr->daddr; + fl6->saddr = reverse ? hdr->daddr : hdr->saddr; +diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c +index 7a1e0fc..e096025 100644 +--- a/net/ipx/af_ipx.c ++++ b/net/ipx/af_ipx.c +@@ -1823,8 +1823,6 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, + if (skb->tstamp.tv64) + sk->sk_stamp = skb->tstamp; + +- msg->msg_namelen = sizeof(*sipx); +- + if (sipx) { + sipx->sipx_family = AF_IPX; + sipx->sipx_port = ipx->ipx_source.sock; +@@ -1832,6 +1830,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, + sipx->sipx_network = IPX_SKB_CB(skb)->ipx_source_net; + sipx->sipx_type = ipx->ipx_type; + sipx->sipx_zero = 0; ++ msg->msg_namelen = sizeof(*sipx); + } + rc = copied; + +diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c +index 0578d4f..a5e62ef5 100644 +--- a/net/irda/af_irda.c ++++ b/net/irda/af_irda.c +@@ -1385,8 +1385,6 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, + + IRDA_DEBUG(4, "%s()\n", __func__); + +- msg->msg_namelen = 0; +- + skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, + flags & MSG_DONTWAIT, &err); + if (!skb) +@@ -1451,8 +1449,6 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, + target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); + timeo = sock_rcvtimeo(sk, noblock); + +- msg->msg_namelen = 0; +- + do { + int chunk; + struct sk_buff *skb = skb_dequeue(&sk->sk_receive_queue); +diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c +index 168aff5..c4b7218 100644 +--- a/net/iucv/af_iucv.c ++++ b/net/iucv/af_iucv.c +@@ -1324,8 +1324,6 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + int err = 0; + u32 offset; + +- msg->msg_namelen = 0; +- + if ((sk->sk_state == IUCV_DISCONN) && + skb_queue_empty(&iucv->backlog_skb_q) && + skb_queue_empty(&sk->sk_receive_queue) && +diff --git a/net/key/af_key.c b/net/key/af_key.c +index 911ef03..545f047 100644 +--- a/net/key/af_key.c ++++ b/net/key/af_key.c +@@ -3616,7 +3616,6 @@ static int pfkey_recvmsg(struct kiocb *kiocb, + if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT)) + goto out; + +- msg->msg_namelen = 0; + skb = skb_recv_datagram(sk, flags, flags & MSG_DONTWAIT, &err); + if (skb == NULL) + goto out; +diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c +index 571db8d..da1a1ce 100644 +--- a/net/l2tp/l2tp_ip.c ++++ b/net/l2tp/l2tp_ip.c +@@ -518,9 +518,6 @@ static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m + if (flags & MSG_OOB) + goto out; + +- if (addr_len) +- *addr_len = sizeof(*sin); +- + skb = skb_recv_datagram(sk, flags, noblock, &err); + if (!skb) + goto out; +@@ -543,6 +540,7 @@ static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m + sin->sin_addr.s_addr = ip_hdr(skb)->saddr; + sin->sin_port = 0; + memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); ++ *addr_len = sizeof(*sin); + } + if (inet->cmsg_flags) + ip_cmsg_recv(msg, skb); +diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c +index b8a6039..e6e8408 100644 +--- a/net/l2tp/l2tp_ip6.c ++++ b/net/l2tp/l2tp_ip6.c +@@ -665,7 +665,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk, + *addr_len = sizeof(*lsa); + + if (flags & MSG_ERRQUEUE) +- return ipv6_recv_error(sk, msg, len); ++ return ipv6_recv_error(sk, msg, len, addr_len); + + skb = skb_recv_datagram(sk, flags, noblock, &err); + if (!skb) +diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c +index 8c46b27..44441c0 100644 +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -197,8 +197,6 @@ static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock, + if (sk->sk_state & PPPOX_BOUND) + goto end; + +- msg->msg_namelen = 0; +- + err = 0; + skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, + flags & MSG_DONTWAIT, &err); +diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c +index 6cba486..7b01b9f 100644 +--- a/net/llc/af_llc.c ++++ b/net/llc/af_llc.c +@@ -720,8 +720,6 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, + int target; /* Read at least this many bytes */ + long timeo; + +- msg->msg_namelen = 0; +- + lock_sock(sk); + copied = -ENOTCONN; + if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN)) +diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c +index 74fd00c..3581736 100644 +--- a/net/netfilter/ipvs/ip_vs_core.c ++++ b/net/netfilter/ipvs/ip_vs_core.c +@@ -1139,12 +1139,6 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) + ip_vs_fill_iph_skb(af, skb, &iph); + #ifdef CONFIG_IP_VS_IPV6 + if (af == AF_INET6) { +- if (!iph.fragoffs && skb_nfct_reasm(skb)) { +- struct sk_buff *reasm = skb_nfct_reasm(skb); +- /* Save fw mark for coming frags */ +- reasm->ipvs_property = 1; +- reasm->mark = skb->mark; +- } + if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { + int related; + int verdict = ip_vs_out_icmp_v6(skb, &related, +@@ -1614,12 +1608,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) + + #ifdef CONFIG_IP_VS_IPV6 + if (af == AF_INET6) { +- if (!iph.fragoffs && skb_nfct_reasm(skb)) { +- struct sk_buff *reasm = skb_nfct_reasm(skb); +- /* Save fw mark for coming frags. */ +- reasm->ipvs_property = 1; +- reasm->mark = skb->mark; +- } + if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { + int related; + int verdict = ip_vs_in_icmp_v6(skb, &related, hooknum, +@@ -1671,9 +1659,8 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) + /* sorry, all this trouble for a no-hit :) */ + IP_VS_DBG_PKT(12, af, pp, skb, 0, + "ip_vs_in: packet continues traversal as normal"); +- if (iph.fragoffs && !skb_nfct_reasm(skb)) { ++ if (iph.fragoffs) { + /* Fragment that couldn't be mapped to a conn entry +- * and don't have any pointer to a reasm skb + * is missing module nf_defrag_ipv6 + */ + IP_VS_DBG_RL("Unhandled frag, load nf_defrag_ipv6\n"); +@@ -1756,38 +1743,6 @@ ip_vs_local_request4(unsigned int hooknum, struct sk_buff *skb, + #ifdef CONFIG_IP_VS_IPV6 + + /* +- * AF_INET6 fragment handling +- * Copy info from first fragment, to the rest of them. +- */ +-static unsigned int +-ip_vs_preroute_frag6(unsigned int hooknum, struct sk_buff *skb, +- const struct net_device *in, +- const struct net_device *out, +- int (*okfn)(struct sk_buff *)) +-{ +- struct sk_buff *reasm = skb_nfct_reasm(skb); +- struct net *net; +- +- /* Skip if not a "replay" from nf_ct_frag6_output or first fragment. +- * ipvs_property is set when checking first fragment +- * in ip_vs_in() and ip_vs_out(). +- */ +- if (reasm) +- IP_VS_DBG(2, "Fragment recv prop:%d\n", reasm->ipvs_property); +- if (!reasm || !reasm->ipvs_property) +- return NF_ACCEPT; +- +- net = skb_net(skb); +- if (!net_ipvs(net)->enable) +- return NF_ACCEPT; +- +- /* Copy stored fw mark, saved in ip_vs_{in,out} */ +- skb->mark = reasm->mark; +- +- return NF_ACCEPT; +-} +- +-/* + * AF_INET6 handler in NF_INET_LOCAL_IN chain + * Schedule and forward packets from remote clients + */ +@@ -1924,14 +1879,6 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { + .priority = 100, + }, + #ifdef CONFIG_IP_VS_IPV6 +- /* After mangle & nat fetch 2:nd fragment and following */ +- { +- .hook = ip_vs_preroute_frag6, +- .owner = THIS_MODULE, +- .pf = NFPROTO_IPV6, +- .hooknum = NF_INET_PRE_ROUTING, +- .priority = NF_IP6_PRI_NAT_DST + 1, +- }, + /* After packet filtering, change source only for VS/NAT */ + { + .hook = ip_vs_reply6, +diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c +index 9ef22bd..bed5f70 100644 +--- a/net/netfilter/ipvs/ip_vs_pe_sip.c ++++ b/net/netfilter/ipvs/ip_vs_pe_sip.c +@@ -65,7 +65,6 @@ static int get_callid(const char *dptr, unsigned int dataoff, + static int + ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb) + { +- struct sk_buff *reasm = skb_nfct_reasm(skb); + struct ip_vs_iphdr iph; + unsigned int dataoff, datalen, matchoff, matchlen; + const char *dptr; +@@ -79,15 +78,10 @@ ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb) + /* todo: IPv6 fragments: + * I think this only should be done for the first fragment. /HS + */ +- if (reasm) { +- skb = reasm; +- dataoff = iph.thoff_reasm + sizeof(struct udphdr); +- } else +- dataoff = iph.len + sizeof(struct udphdr); ++ dataoff = iph.len + sizeof(struct udphdr); + + if (dataoff >= skb->len) + return -EINVAL; +- /* todo: Check if this will mess-up the reasm skb !!! /HS */ + retc = skb_linearize(skb); + if (retc < 0) + return retc; +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index 8df7f64..6135635 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -2335,8 +2335,6 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, + } + #endif + +- msg->msg_namelen = 0; +- + copied = data_skb->len; + if (len < copied) { + msg->msg_flags |= MSG_TRUNC; +diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c +index 698814b..53c19a3 100644 +--- a/net/netrom/af_netrom.c ++++ b/net/netrom/af_netrom.c +@@ -1179,10 +1179,9 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, + sax->sax25_family = AF_NETROM; + skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call, + AX25_ADDR_LEN); ++ msg->msg_namelen = sizeof(*sax); + } + +- msg->msg_namelen = sizeof(*sax); +- + skb_free_datagram(sk, skb); + + release_sock(sk); +diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c +index d308402..824c605 100644 +--- a/net/nfc/llcp_sock.c ++++ b/net/nfc/llcp_sock.c +@@ -807,8 +807,6 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, + + pr_debug("%p %zu\n", sk, len); + +- msg->msg_namelen = 0; +- + lock_sock(sk); + + if (sk->sk_state == LLCP_CLOSED && +diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c +index 313bf1b..5d11f4a 100644 +--- a/net/nfc/rawsock.c ++++ b/net/nfc/rawsock.c +@@ -241,8 +241,6 @@ static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock, + if (!skb) + return rc; + +- msg->msg_namelen = 0; +- + copied = skb->len; + if (len < copied) { + msg->msg_flags |= MSG_TRUNC; +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 2e8286b..ba2548b 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -244,11 +244,15 @@ static void __fanout_link(struct sock *sk, struct packet_sock *po); + static void register_prot_hook(struct sock *sk) + { + struct packet_sock *po = pkt_sk(sk); ++ + if (!po->running) { +- if (po->fanout) ++ if (po->fanout) { + __fanout_link(sk, po); +- else ++ } else { + dev_add_pack(&po->prot_hook); ++ rcu_assign_pointer(po->cached_dev, po->prot_hook.dev); ++ } ++ + sock_hold(sk); + po->running = 1; + } +@@ -266,10 +270,13 @@ static void __unregister_prot_hook(struct sock *sk, bool sync) + struct packet_sock *po = pkt_sk(sk); + + po->running = 0; +- if (po->fanout) ++ if (po->fanout) { + __fanout_unlink(sk, po); +- else ++ } else { + __dev_remove_pack(&po->prot_hook); ++ RCU_INIT_POINTER(po->cached_dev, NULL); ++ } ++ + __sock_put(sk); + + if (sync) { +@@ -432,9 +439,9 @@ static void prb_shutdown_retire_blk_timer(struct packet_sock *po, + + pkc = tx_ring ? &po->tx_ring.prb_bdqc : &po->rx_ring.prb_bdqc; + +- spin_lock(&rb_queue->lock); ++ spin_lock_bh(&rb_queue->lock); + pkc->delete_blk_timer = 1; +- spin_unlock(&rb_queue->lock); ++ spin_unlock_bh(&rb_queue->lock); + + prb_del_retire_blk_timer(pkc); + } +@@ -2052,12 +2059,24 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, + return tp_len; + } + ++static struct net_device *packet_cached_dev_get(struct packet_sock *po) ++{ ++ struct net_device *dev; ++ ++ rcu_read_lock(); ++ dev = rcu_dereference(po->cached_dev); ++ if (dev) ++ dev_hold(dev); ++ rcu_read_unlock(); ++ ++ return dev; ++} ++ + static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) + { + struct sk_buff *skb; + struct net_device *dev; + __be16 proto; +- bool need_rls_dev = false; + int err, reserve = 0; + void *ph; + struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name; +@@ -2070,7 +2089,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) + mutex_lock(&po->pg_vec_lock); + + if (saddr == NULL) { +- dev = po->prot_hook.dev; ++ dev = packet_cached_dev_get(po); + proto = po->num; + addr = NULL; + } else { +@@ -2084,19 +2103,17 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) + proto = saddr->sll_protocol; + addr = saddr->sll_addr; + dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex); +- need_rls_dev = true; + } + + err = -ENXIO; + if (unlikely(dev == NULL)) + goto out; +- +- reserve = dev->hard_header_len; +- + err = -ENETDOWN; + if (unlikely(!(dev->flags & IFF_UP))) + goto out_put; + ++ reserve = dev->hard_header_len; ++ + size_max = po->tx_ring.frame_size + - (po->tp_hdrlen - sizeof(struct sockaddr_ll)); + +@@ -2173,8 +2190,7 @@ out_status: + __packet_set_status(po, ph, status); + kfree_skb(skb); + out_put: +- if (need_rls_dev) +- dev_put(dev); ++ dev_put(dev); + out: + mutex_unlock(&po->pg_vec_lock); + return err; +@@ -2212,7 +2228,6 @@ static int packet_snd(struct socket *sock, + struct sk_buff *skb; + struct net_device *dev; + __be16 proto; +- bool need_rls_dev = false; + unsigned char *addr; + int err, reserve = 0; + struct virtio_net_hdr vnet_hdr = { 0 }; +@@ -2228,7 +2243,7 @@ static int packet_snd(struct socket *sock, + */ + + if (saddr == NULL) { +- dev = po->prot_hook.dev; ++ dev = packet_cached_dev_get(po); + proto = po->num; + addr = NULL; + } else { +@@ -2240,19 +2255,17 @@ static int packet_snd(struct socket *sock, + proto = saddr->sll_protocol; + addr = saddr->sll_addr; + dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex); +- need_rls_dev = true; + } + + err = -ENXIO; +- if (dev == NULL) ++ if (unlikely(dev == NULL)) + goto out_unlock; +- if (sock->type == SOCK_RAW) +- reserve = dev->hard_header_len; +- + err = -ENETDOWN; +- if (!(dev->flags & IFF_UP)) ++ if (unlikely(!(dev->flags & IFF_UP))) + goto out_unlock; + ++ if (sock->type == SOCK_RAW) ++ reserve = dev->hard_header_len; + if (po->has_vnet_hdr) { + vnet_hdr_len = sizeof(vnet_hdr); + +@@ -2386,15 +2399,14 @@ static int packet_snd(struct socket *sock, + if (err > 0 && (err = net_xmit_errno(err)) != 0) + goto out_unlock; + +- if (need_rls_dev) +- dev_put(dev); ++ dev_put(dev); + + return len; + + out_free: + kfree_skb(skb); + out_unlock: +- if (dev && need_rls_dev) ++ if (dev) + dev_put(dev); + out: + return err; +@@ -2614,6 +2626,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol, + po = pkt_sk(sk); + sk->sk_family = PF_PACKET; + po->num = proto; ++ RCU_INIT_POINTER(po->cached_dev, NULL); + + sk->sk_destruct = packet_sock_destruct; + sk_refcnt_debug_inc(sk); +@@ -2660,7 +2673,6 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, + struct sock *sk = sock->sk; + struct sk_buff *skb; + int copied, err; +- struct sockaddr_ll *sll; + int vnet_hdr_len = 0; + + err = -EINVAL; +@@ -2744,22 +2756,10 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, + goto out_free; + } + +- /* +- * If the address length field is there to be filled in, we fill +- * it in now. ++ /* You lose any data beyond the buffer you gave. If it worries ++ * a user program they can ask the device for its MTU ++ * anyway. + */ +- +- sll = &PACKET_SKB_CB(skb)->sa.ll; +- if (sock->type == SOCK_PACKET) +- msg->msg_namelen = sizeof(struct sockaddr_pkt); +- else +- msg->msg_namelen = sll->sll_halen + offsetof(struct sockaddr_ll, sll_addr); +- +- /* +- * You lose any data beyond the buffer you gave. If it worries a +- * user program they can ask the device for its MTU anyway. +- */ +- + copied = skb->len; + if (copied > len) { + copied = len; +@@ -2772,9 +2772,20 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, + + sock_recv_ts_and_drops(msg, sk, skb); + +- if (msg->msg_name) ++ if (msg->msg_name) { ++ /* If the address length field is there to be filled ++ * in, we fill it in now. ++ */ ++ if (sock->type == SOCK_PACKET) { ++ msg->msg_namelen = sizeof(struct sockaddr_pkt); ++ } else { ++ struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll; ++ msg->msg_namelen = sll->sll_halen + ++ offsetof(struct sockaddr_ll, sll_addr); ++ } + memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa, + msg->msg_namelen); ++ } + + if (pkt_sk(sk)->auxdata) { + struct tpacket_auxdata aux; +diff --git a/net/packet/internal.h b/net/packet/internal.h +index c4e4b45..1035fa2 100644 +--- a/net/packet/internal.h ++++ b/net/packet/internal.h +@@ -113,6 +113,7 @@ struct packet_sock { + unsigned int tp_loss:1; + unsigned int tp_tx_has_off:1; + unsigned int tp_tstamp; ++ struct net_device __rcu *cached_dev; + struct packet_type prot_hook ____cacheline_aligned_in_smp; + }; + +diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c +index 12c30f3..38946b2 100644 +--- a/net/phonet/datagram.c ++++ b/net/phonet/datagram.c +@@ -139,9 +139,6 @@ static int pn_recvmsg(struct kiocb *iocb, struct sock *sk, + MSG_CMSG_COMPAT)) + goto out_nofree; + +- if (addr_len) +- *addr_len = sizeof(sa); +- + skb = skb_recv_datagram(sk, flags, noblock, &rval); + if (skb == NULL) + goto out_nofree; +@@ -162,8 +159,10 @@ static int pn_recvmsg(struct kiocb *iocb, struct sock *sk, + + rval = (flags & MSG_TRUNC) ? skb->len : copylen; + +- if (msg->msg_name != NULL) +- memcpy(msg->msg_name, &sa, sizeof(struct sockaddr_pn)); ++ if (msg->msg_name != NULL) { ++ memcpy(msg->msg_name, &sa, sizeof(sa)); ++ *addr_len = sizeof(sa); ++ } + + out: + skb_free_datagram(sk, skb); +diff --git a/net/rds/recv.c b/net/rds/recv.c +index 9f0f17c..de339b2 100644 +--- a/net/rds/recv.c ++++ b/net/rds/recv.c +@@ -410,8 +410,6 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, + + rdsdebug("size %zu flags 0x%x timeo %ld\n", size, msg_flags, timeo); + +- msg->msg_namelen = 0; +- + if (msg_flags & MSG_OOB) + goto out; + +diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c +index e98fcfb..33af772 100644 +--- a/net/rose/af_rose.c ++++ b/net/rose/af_rose.c +@@ -1216,7 +1216,6 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock, + { + struct sock *sk = sock->sk; + struct rose_sock *rose = rose_sk(sk); +- struct sockaddr_rose *srose = (struct sockaddr_rose *)msg->msg_name; + size_t copied; + unsigned char *asmptr; + struct sk_buff *skb; +@@ -1252,8 +1251,11 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock, + + skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + +- if (srose != NULL) { +- memset(srose, 0, msg->msg_namelen); ++ if (msg->msg_name) { ++ struct sockaddr_rose *srose; ++ ++ memset(msg->msg_name, 0, sizeof(struct full_sockaddr_rose)); ++ srose = msg->msg_name; + srose->srose_family = AF_ROSE; + srose->srose_addr = rose->dest_addr; + srose->srose_call = rose->dest_call; +diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c +index 4b48687..898492a 100644 +--- a/net/rxrpc/ar-recvmsg.c ++++ b/net/rxrpc/ar-recvmsg.c +@@ -143,10 +143,13 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock, + + /* copy the peer address and timestamp */ + if (!continue_call) { +- if (msg->msg_name && msg->msg_namelen > 0) ++ if (msg->msg_name) { ++ size_t len = ++ sizeof(call->conn->trans->peer->srx); + memcpy(msg->msg_name, +- &call->conn->trans->peer->srx, +- sizeof(call->conn->trans->peer->srx)); ++ &call->conn->trans->peer->srx, len); ++ msg->msg_namelen = len; ++ } + sock_recv_ts_and_drops(msg, &rx->sk, skb); + } + +diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c +index a9dfdda..2e55f81 100644 +--- a/net/sched/sch_fq.c ++++ b/net/sched/sch_fq.c +@@ -88,7 +88,7 @@ struct fq_sched_data { + struct fq_flow internal; /* for non classified or high prio packets */ + u32 quantum; + u32 initial_quantum; +- u32 flow_default_rate;/* rate per flow : bytes per second */ ++ u32 flow_refill_delay; + u32 flow_max_rate; /* optional max rate per flow */ + u32 flow_plimit; /* max packets per flow */ + struct rb_root *fq_root; +@@ -115,6 +115,7 @@ static struct fq_flow detached, throttled; + static void fq_flow_set_detached(struct fq_flow *f) + { + f->next = &detached; ++ f->age = jiffies; + } + + static bool fq_flow_is_detached(const struct fq_flow *f) +@@ -209,21 +210,15 @@ static void fq_gc(struct fq_sched_data *q, + } + } + +-static const u8 prio2band[TC_PRIO_MAX + 1] = { +- 1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1 +-}; +- + static struct fq_flow *fq_classify(struct sk_buff *skb, struct fq_sched_data *q) + { + struct rb_node **p, *parent; + struct sock *sk = skb->sk; + struct rb_root *root; + struct fq_flow *f; +- int band; + + /* warning: no starvation prevention... */ +- band = prio2band[skb->priority & TC_PRIO_MAX]; +- if (unlikely(band == 0)) ++ if (unlikely((skb->priority & TC_PRIO_MAX) == TC_PRIO_CONTROL)) + return &q->internal; + + if (unlikely(!sk)) { +@@ -372,17 +367,20 @@ static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch) + } + + f->qlen++; +- flow_queue_add(f, skb); + if (skb_is_retransmit(skb)) + q->stat_tcp_retrans++; + sch->qstats.backlog += qdisc_pkt_len(skb); + if (fq_flow_is_detached(f)) { + fq_flow_add_tail(&q->new_flows, f); +- if (q->quantum > f->credit) +- f->credit = q->quantum; ++ if (time_after(jiffies, f->age + q->flow_refill_delay)) ++ f->credit = max_t(u32, f->credit, q->quantum); + q->inactive_flows--; + qdisc_unthrottled(sch); + } ++ ++ /* Note: this overwrites f->age */ ++ flow_queue_add(f, skb); ++ + if (unlikely(f == &q->internal)) { + q->stat_internal_packets++; + qdisc_unthrottled(sch); +@@ -460,7 +458,6 @@ begin: + fq_flow_add_tail(&q->old_flows, f); + } else { + fq_flow_set_detached(f); +- f->age = jiffies; + q->inactive_flows++; + } + goto begin; +@@ -614,6 +611,7 @@ static const struct nla_policy fq_policy[TCA_FQ_MAX + 1] = { + [TCA_FQ_FLOW_DEFAULT_RATE] = { .type = NLA_U32 }, + [TCA_FQ_FLOW_MAX_RATE] = { .type = NLA_U32 }, + [TCA_FQ_BUCKETS_LOG] = { .type = NLA_U32 }, ++ [TCA_FQ_FLOW_REFILL_DELAY] = { .type = NLA_U32 }, + }; + + static int fq_change(struct Qdisc *sch, struct nlattr *opt) +@@ -655,7 +653,8 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt) + q->initial_quantum = nla_get_u32(tb[TCA_FQ_INITIAL_QUANTUM]); + + if (tb[TCA_FQ_FLOW_DEFAULT_RATE]) +- q->flow_default_rate = nla_get_u32(tb[TCA_FQ_FLOW_DEFAULT_RATE]); ++ pr_warn_ratelimited("sch_fq: defrate %u ignored.\n", ++ nla_get_u32(tb[TCA_FQ_FLOW_DEFAULT_RATE])); + + if (tb[TCA_FQ_FLOW_MAX_RATE]) + q->flow_max_rate = nla_get_u32(tb[TCA_FQ_FLOW_MAX_RATE]); +@@ -669,6 +668,12 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt) + err = -EINVAL; + } + ++ if (tb[TCA_FQ_FLOW_REFILL_DELAY]) { ++ u32 usecs_delay = nla_get_u32(tb[TCA_FQ_FLOW_REFILL_DELAY]) ; ++ ++ q->flow_refill_delay = usecs_to_jiffies(usecs_delay); ++ } ++ + if (!err) + err = fq_resize(q, fq_log); + +@@ -704,7 +709,7 @@ static int fq_init(struct Qdisc *sch, struct nlattr *opt) + q->flow_plimit = 100; + q->quantum = 2 * psched_mtu(qdisc_dev(sch)); + q->initial_quantum = 10 * psched_mtu(qdisc_dev(sch)); +- q->flow_default_rate = 0; ++ q->flow_refill_delay = msecs_to_jiffies(40); + q->flow_max_rate = ~0U; + q->rate_enable = 1; + q->new_flows.first = NULL; +@@ -731,15 +736,16 @@ static int fq_dump(struct Qdisc *sch, struct sk_buff *skb) + if (opts == NULL) + goto nla_put_failure; + +- /* TCA_FQ_FLOW_DEFAULT_RATE is not used anymore, +- * do not bother giving its value +- */ ++ /* TCA_FQ_FLOW_DEFAULT_RATE is not used anymore */ ++ + if (nla_put_u32(skb, TCA_FQ_PLIMIT, sch->limit) || + nla_put_u32(skb, TCA_FQ_FLOW_PLIMIT, q->flow_plimit) || + nla_put_u32(skb, TCA_FQ_QUANTUM, q->quantum) || + nla_put_u32(skb, TCA_FQ_INITIAL_QUANTUM, q->initial_quantum) || + nla_put_u32(skb, TCA_FQ_RATE_ENABLE, q->rate_enable) || + nla_put_u32(skb, TCA_FQ_FLOW_MAX_RATE, q->flow_max_rate) || ++ nla_put_u32(skb, TCA_FQ_FLOW_REFILL_DELAY, ++ jiffies_to_usecs(q->flow_refill_delay)) || + nla_put_u32(skb, TCA_FQ_BUCKETS_LOG, q->fq_trees_log)) + goto nla_put_failure; + +diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c +index 1aaf1b6..6ddda28 100644 +--- a/net/sched/sch_tbf.c ++++ b/net/sched/sch_tbf.c +@@ -21,6 +21,7 @@ + #include <net/netlink.h> + #include <net/sch_generic.h> + #include <net/pkt_sched.h> ++#include <net/tcp.h> + + + /* Simple Token Bucket Filter. +@@ -117,6 +118,22 @@ struct tbf_sched_data { + }; + + ++/* ++ * Return length of individual segments of a gso packet, ++ * including all headers (MAC, IP, TCP/UDP) ++ */ ++static unsigned int skb_gso_seglen(const struct sk_buff *skb) ++{ ++ unsigned int hdr_len = skb_transport_header(skb) - skb_mac_header(skb); ++ const struct skb_shared_info *shinfo = skb_shinfo(skb); ++ ++ if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) ++ hdr_len += tcp_hdrlen(skb); ++ else ++ hdr_len += sizeof(struct udphdr); ++ return hdr_len + shinfo->gso_size; ++} ++ + /* GSO packet is too big, segment it so that tbf can transmit + * each segment in time + */ +@@ -136,12 +153,8 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch) + while (segs) { + nskb = segs->next; + segs->next = NULL; +- if (likely(segs->len <= q->max_size)) { +- qdisc_skb_cb(segs)->pkt_len = segs->len; +- ret = qdisc_enqueue(segs, q->qdisc); +- } else { +- ret = qdisc_reshape_fail(skb, sch); +- } ++ qdisc_skb_cb(segs)->pkt_len = segs->len; ++ ret = qdisc_enqueue(segs, q->qdisc); + if (ret != NET_XMIT_SUCCESS) { + if (net_xmit_drop_count(ret)) + sch->qstats.drops++; +@@ -163,7 +176,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch) + int ret; + + if (qdisc_pkt_len(skb) > q->max_size) { +- if (skb_is_gso(skb)) ++ if (skb_is_gso(skb) && skb_gso_seglen(skb) <= q->max_size) + return tbf_segment(skb, sch); + return qdisc_reshape_fail(skb, sch); + } +@@ -316,6 +329,11 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) + if (max_size < 0) + goto done; + ++ if (max_size < psched_mtu(qdisc_dev(sch))) ++ pr_warn_ratelimited("sch_tbf: burst %u is lower than device %s mtu (%u) !\n", ++ max_size, qdisc_dev(sch)->name, ++ psched_mtu(qdisc_dev(sch))); ++ + if (q->qdisc != &noop_qdisc) { + err = fifo_set_limit(q->qdisc, qopt->limit); + if (err) +diff --git a/net/socket.c b/net/socket.c +index c226ace..e83c416 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -221,12 +221,13 @@ static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen, + int err; + int len; + ++ BUG_ON(klen > sizeof(struct sockaddr_storage)); + err = get_user(len, ulen); + if (err) + return err; + if (len > klen) + len = klen; +- if (len < 0 || len > sizeof(struct sockaddr_storage)) ++ if (len < 0) + return -EINVAL; + if (len) { + if (audit_sockaddr(klen, kaddr)) +@@ -1840,8 +1841,10 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, + msg.msg_iov = &iov; + iov.iov_len = size; + iov.iov_base = ubuf; +- msg.msg_name = (struct sockaddr *)&address; +- msg.msg_namelen = sizeof(address); ++ /* Save some cycles and don't copy the address if not needed */ ++ msg.msg_name = addr ? (struct sockaddr *)&address : NULL; ++ /* We assume all kernel code knows the size of sockaddr_storage */ ++ msg.msg_namelen = 0; + if (sock->file->f_flags & O_NONBLOCK) + flags |= MSG_DONTWAIT; + err = sock_recvmsg(sock, &msg, size, flags); +@@ -1970,7 +1973,7 @@ static int copy_msghdr_from_user(struct msghdr *kmsg, + if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) + return -EFAULT; + if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) +- return -EINVAL; ++ kmsg->msg_namelen = sizeof(struct sockaddr_storage); + return 0; + } + +@@ -2221,16 +2224,14 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, + goto out; + } + +- /* +- * Save the user-mode address (verify_iovec will change the +- * kernel msghdr to use the kernel address space) ++ /* Save the user-mode address (verify_iovec will change the ++ * kernel msghdr to use the kernel address space) + */ +- + uaddr = (__force void __user *)msg_sys->msg_name; + uaddr_len = COMPAT_NAMELEN(msg); +- if (MSG_CMSG_COMPAT & flags) { ++ if (MSG_CMSG_COMPAT & flags) + err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE); +- } else ++ else + err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE); + if (err < 0) + goto out_freeiov; +@@ -2239,6 +2240,9 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, + cmsg_ptr = (unsigned long)msg_sys->msg_control; + msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); + ++ /* We assume all kernel code knows the size of sockaddr_storage */ ++ msg_sys->msg_namelen = 0; ++ + if (sock->file->f_flags & O_NONBLOCK) + flags |= MSG_DONTWAIT; + err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, +diff --git a/net/tipc/socket.c b/net/tipc/socket.c +index 6cc7ddd..dffdbea 100644 +--- a/net/tipc/socket.c ++++ b/net/tipc/socket.c +@@ -984,9 +984,6 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, + goto exit; + } + +- /* will be updated in set_orig_addr() if needed */ +- m->msg_namelen = 0; +- + timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); + restart: + +@@ -1095,9 +1092,6 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, + goto exit; + } + +- /* will be updated in set_orig_addr() if needed */ +- m->msg_namelen = 0; +- + target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); + timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); + +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index c1f403b..01625cc 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1754,7 +1754,6 @@ static void unix_copy_addr(struct msghdr *msg, struct sock *sk) + { + struct unix_sock *u = unix_sk(sk); + +- msg->msg_namelen = 0; + if (u->addr) { + msg->msg_namelen = u->addr->len; + memcpy(msg->msg_name, u->addr->name, u->addr->len); +@@ -1778,8 +1777,6 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, + if (flags&MSG_OOB) + goto out; + +- msg->msg_namelen = 0; +- + err = mutex_lock_interruptible(&u->readlock); + if (err) { + err = sock_intr_errno(sock_rcvtimeo(sk, noblock)); +@@ -1924,8 +1921,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, + target = sock_rcvlowat(sk, flags&MSG_WAITALL, size); + timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT); + +- msg->msg_namelen = 0; +- + /* Lock the socket to prevent queue disordering + * while sleeps in memcpy_tomsg + */ +diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c +index 545c08b..5adfd94 100644 +--- a/net/vmw_vsock/af_vsock.c ++++ b/net/vmw_vsock/af_vsock.c +@@ -1662,8 +1662,6 @@ vsock_stream_recvmsg(struct kiocb *kiocb, + vsk = vsock_sk(sk); + err = 0; + +- msg->msg_namelen = 0; +- + lock_sock(sk); + + if (sk->sk_state != SS_CONNECTED) { +diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c +index 9d69866..687360d 100644 +--- a/net/vmw_vsock/vmci_transport.c ++++ b/net/vmw_vsock/vmci_transport.c +@@ -1746,8 +1746,6 @@ static int vmci_transport_dgram_dequeue(struct kiocb *kiocb, + if (flags & MSG_OOB || flags & MSG_ERRQUEUE) + return -EOPNOTSUPP; + +- msg->msg_namelen = 0; +- + /* Retrieve the head sk_buff from the socket's receive queue. */ + err = 0; + skb = skb_recv_datagram(&vsk->sk, flags, noblock, &err); +diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c +index 45a3ab5..7622789 100644 +--- a/net/x25/af_x25.c ++++ b/net/x25/af_x25.c +@@ -1340,10 +1340,9 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, + if (sx25) { + sx25->sx25_family = AF_X25; + sx25->sx25_addr = x25->dest_addr; ++ msg->msg_namelen = sizeof(*sx25); + } + +- msg->msg_namelen = sizeof(struct sockaddr_x25); +- + x25_check_rbuf(sk); + rc = copied; + out_free_dgram: |