Update to 3.3.4
svn path=/dists/trunk/linux-2.6/; revision=18965
This commit is contained in:
parent
40fc14743c
commit
6eb980cbbb
|
@ -1,3 +1,11 @@
|
|||
linux-2.6 (3.3.4-1~experimental.1) UNRELEASED; urgency=low
|
||||
|
||||
* New upstream stable update:
|
||||
http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.3.3
|
||||
http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.3.4
|
||||
|
||||
-- Ben Hutchings <ben@decadent.org.uk> Mon, 30 Apr 2012 04:02:33 +0100
|
||||
|
||||
linux-2.6 (3.3.2-1~experimental.1) experimental; urgency=low
|
||||
|
||||
* New upstream stable update:
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
From: Chris Metcalf <cmetcalf@tilera.com>
|
||||
Date: Thu, 12 Apr 2012 12:49:15 -0700
|
||||
Subject: [PATCH] hugetlb: fix race condition in hugetlb_fault()
|
||||
|
||||
commit 66aebce747eaf9bc456bf1f1b217d8db843031d0 upstream.
|
||||
|
||||
The race is as follows:
|
||||
|
||||
Suppose a multi-threaded task forks a new process (on cpu A), thus
|
||||
bumping up the ref count on all the pages. While the fork is occurring
|
||||
(and thus we have marked all the PTEs as read-only), another thread in
|
||||
the original process (on cpu B) tries to write to a huge page, taking an
|
||||
access violation from the write-protect and calling hugetlb_cow(). Now,
|
||||
suppose the fork() fails. It will undo the COW and decrement the ref
|
||||
count on the pages, so the ref count on the huge page drops back to 1.
|
||||
Meanwhile hugetlb_cow() also decrements the ref count by one on the
|
||||
original page, since the original address space doesn't need it any
|
||||
more, having copied a new page to replace the original page. This
|
||||
leaves the ref count at zero, and when we call unlock_page(), we panic.
|
||||
|
||||
fork on CPU A fault on CPU B
|
||||
============= ==============
|
||||
...
|
||||
down_write(&parent->mmap_sem);
|
||||
down_write_nested(&child->mmap_sem);
|
||||
...
|
||||
while duplicating vmas
|
||||
if error
|
||||
break;
|
||||
...
|
||||
up_write(&child->mmap_sem);
|
||||
up_write(&parent->mmap_sem); ...
|
||||
down_read(&parent->mmap_sem);
|
||||
...
|
||||
lock_page(page);
|
||||
handle COW
|
||||
page_mapcount(old_page) == 2
|
||||
alloc and prepare new_page
|
||||
...
|
||||
handle error
|
||||
page_remove_rmap(page);
|
||||
put_page(page);
|
||||
...
|
||||
fold new_page into pte
|
||||
page_remove_rmap(page);
|
||||
put_page(page);
|
||||
...
|
||||
oops ==> unlock_page(page);
|
||||
up_read(&parent->mmap_sem);
|
||||
|
||||
The solution is to take an extra reference to the page while we are
|
||||
holding the lock on it.
|
||||
|
||||
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
|
||||
Cc: Hillf Danton <dhillf@gmail.com>
|
||||
Cc: Michal Hocko <mhocko@suse.cz>
|
||||
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
|
||||
Cc: Hugh Dickins <hughd@google.com>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
---
|
||||
mm/hugetlb.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
|
||||
index b8ce6f4..cd65cb1 100644
|
||||
--- a/mm/hugetlb.c
|
||||
+++ b/mm/hugetlb.c
|
||||
@@ -2791,6 +2791,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
* so no worry about deadlock.
|
||||
*/
|
||||
page = pte_page(entry);
|
||||
+ get_page(page);
|
||||
if (page != pagecache_page)
|
||||
lock_page(page);
|
||||
|
||||
@@ -2822,6 +2823,7 @@ out_page_table_lock:
|
||||
}
|
||||
if (page != pagecache_page)
|
||||
unlock_page(page);
|
||||
+ put_page(page);
|
||||
|
||||
out_mutex:
|
||||
mutex_unlock(&hugetlb_instantiation_mutex);
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
From: Eric Dumazet <eric.dumazet@gmail.com>
|
||||
Date: Mon, 2 Apr 2012 22:33:02 +0000
|
||||
Subject: [PATCH] net: fix /proc/net/dev regression
|
||||
|
||||
commit 2def16ae6b0c77571200f18ba4be049b03d75579 upstream.
|
||||
|
||||
Commit f04565ddf52 (dev: use name hash for dev_seq_ops) added a second
|
||||
regression, as some devices are missing from /proc/net/dev if many
|
||||
devices are defined.
|
||||
|
||||
When seq_file buffer is filled, the last ->next/show() method is
|
||||
canceled (pos value is reverted to value prior ->next() call)
|
||||
|
||||
Problem is after above commit, we dont restart the lookup at right
|
||||
position in ->start() method.
|
||||
|
||||
Fix this by removing the internal 'pos' pointer added in commit, since
|
||||
we need to use the 'loff_t *pos' provided by seq_file layer.
|
||||
|
||||
This also reverts commit 5cac98dd0 (net: Fix corruption
|
||||
in /proc/*/net/dev_mcast), since its not needed anymore.
|
||||
|
||||
Reported-by: Ben Greear <greearb@candelatech.com>
|
||||
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
|
||||
Cc: Mihai Maruseac <mmaruseac@ixiacom.com>
|
||||
Tested-by: Ben Greear <greearb@candelatech.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
include/linux/netdevice.h | 2 --
|
||||
net/core/dev.c | 58 ++++++++++-----------------------------------
|
||||
net/core/dev_addr_lists.c | 3 ++-
|
||||
3 files changed, 15 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
|
||||
index 1f77540..5cbaa20 100644
|
||||
--- a/include/linux/netdevice.h
|
||||
+++ b/include/linux/netdevice.h
|
||||
@@ -2604,8 +2604,6 @@ extern void net_disable_timestamp(void);
|
||||
extern void *dev_seq_start(struct seq_file *seq, loff_t *pos);
|
||||
extern void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos);
|
||||
extern void dev_seq_stop(struct seq_file *seq, void *v);
|
||||
-extern int dev_seq_open_ops(struct inode *inode, struct file *file,
|
||||
- const struct seq_operations *ops);
|
||||
#endif
|
||||
|
||||
extern int netdev_class_create_file(struct class_attribute *class_attr);
|
||||
diff --git a/net/core/dev.c b/net/core/dev.c
|
||||
index 6c7dc9d..c25d453 100644
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -4028,54 +4028,41 @@ static int dev_ifconf(struct net *net, char __user *arg)
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
||||
-#define BUCKET_SPACE (32 - NETDEV_HASHBITS)
|
||||
-
|
||||
-struct dev_iter_state {
|
||||
- struct seq_net_private p;
|
||||
- unsigned int pos; /* bucket << BUCKET_SPACE + offset */
|
||||
-};
|
||||
+#define BUCKET_SPACE (32 - NETDEV_HASHBITS - 1)
|
||||
|
||||
#define get_bucket(x) ((x) >> BUCKET_SPACE)
|
||||
#define get_offset(x) ((x) & ((1 << BUCKET_SPACE) - 1))
|
||||
#define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o))
|
||||
|
||||
-static inline struct net_device *dev_from_same_bucket(struct seq_file *seq)
|
||||
+static inline struct net_device *dev_from_same_bucket(struct seq_file *seq, loff_t *pos)
|
||||
{
|
||||
- struct dev_iter_state *state = seq->private;
|
||||
struct net *net = seq_file_net(seq);
|
||||
struct net_device *dev;
|
||||
struct hlist_node *p;
|
||||
struct hlist_head *h;
|
||||
- unsigned int count, bucket, offset;
|
||||
+ unsigned int count = 0, offset = get_offset(*pos);
|
||||
|
||||
- bucket = get_bucket(state->pos);
|
||||
- offset = get_offset(state->pos);
|
||||
- h = &net->dev_name_head[bucket];
|
||||
- count = 0;
|
||||
+ h = &net->dev_name_head[get_bucket(*pos)];
|
||||
hlist_for_each_entry_rcu(dev, p, h, name_hlist) {
|
||||
- if (count++ == offset) {
|
||||
- state->pos = set_bucket_offset(bucket, count);
|
||||
+ if (++count == offset)
|
||||
return dev;
|
||||
- }
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static inline struct net_device *dev_from_new_bucket(struct seq_file *seq)
|
||||
+static inline struct net_device *dev_from_bucket(struct seq_file *seq, loff_t *pos)
|
||||
{
|
||||
- struct dev_iter_state *state = seq->private;
|
||||
struct net_device *dev;
|
||||
unsigned int bucket;
|
||||
|
||||
- bucket = get_bucket(state->pos);
|
||||
do {
|
||||
- dev = dev_from_same_bucket(seq);
|
||||
+ dev = dev_from_same_bucket(seq, pos);
|
||||
if (dev)
|
||||
return dev;
|
||||
|
||||
- bucket++;
|
||||
- state->pos = set_bucket_offset(bucket, 0);
|
||||
+ bucket = get_bucket(*pos) + 1;
|
||||
+ *pos = set_bucket_offset(bucket, 1);
|
||||
} while (bucket < NETDEV_HASHENTRIES);
|
||||
|
||||
return NULL;
|
||||
@@ -4088,33 +4075,20 @@ static inline struct net_device *dev_from_new_bucket(struct seq_file *seq)
|
||||
void *dev_seq_start(struct seq_file *seq, loff_t *pos)
|
||||
__acquires(RCU)
|
||||
{
|
||||
- struct dev_iter_state *state = seq->private;
|
||||
-
|
||||
rcu_read_lock();
|
||||
if (!*pos)
|
||||
return SEQ_START_TOKEN;
|
||||
|
||||
- /* check for end of the hash */
|
||||
- if (state->pos == 0 && *pos > 1)
|
||||
+ if (get_bucket(*pos) >= NETDEV_HASHENTRIES)
|
||||
return NULL;
|
||||
|
||||
- return dev_from_new_bucket(seq);
|
||||
+ return dev_from_bucket(seq, pos);
|
||||
}
|
||||
|
||||
void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
|
||||
{
|
||||
- struct net_device *dev;
|
||||
-
|
||||
++*pos;
|
||||
-
|
||||
- if (v == SEQ_START_TOKEN)
|
||||
- return dev_from_new_bucket(seq);
|
||||
-
|
||||
- dev = dev_from_same_bucket(seq);
|
||||
- if (dev)
|
||||
- return dev;
|
||||
-
|
||||
- return dev_from_new_bucket(seq);
|
||||
+ return dev_from_bucket(seq, pos);
|
||||
}
|
||||
|
||||
void dev_seq_stop(struct seq_file *seq, void *v)
|
||||
@@ -4213,13 +4187,7 @@ static const struct seq_operations dev_seq_ops = {
|
||||
static int dev_seq_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open_net(inode, file, &dev_seq_ops,
|
||||
- sizeof(struct dev_iter_state));
|
||||
-}
|
||||
-
|
||||
-int dev_seq_open_ops(struct inode *inode, struct file *file,
|
||||
- const struct seq_operations *ops)
|
||||
-{
|
||||
- return seq_open_net(inode, file, ops, sizeof(struct dev_iter_state));
|
||||
+ sizeof(struct seq_net_private));
|
||||
}
|
||||
|
||||
static const struct file_operations dev_seq_fops = {
|
||||
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c
|
||||
index 29c07fe..626698f 100644
|
||||
--- a/net/core/dev_addr_lists.c
|
||||
+++ b/net/core/dev_addr_lists.c
|
||||
@@ -696,7 +696,8 @@ static const struct seq_operations dev_mc_seq_ops = {
|
||||
|
||||
static int dev_mc_seq_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
- return dev_seq_open_ops(inode, file, &dev_mc_seq_ops);
|
||||
+ return seq_open_net(inode, file, &dev_mc_seq_ops,
|
||||
+ sizeof(struct seq_net_private));
|
||||
}
|
||||
|
||||
static const struct file_operations dev_mc_seq_fops = {
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -58,7 +58,6 @@
|
|||
+ bugfix/arm/ARM-Fix-missing-linux-types.h-inclusion-in-asm-hardw.patch
|
||||
+ bugfix/arm/ARM-Fix-missing-include-for-call-to-soft_restart-in-.patch
|
||||
|
||||
+ bugfix/all/net-fix-proc-net-dev-regression.patch
|
||||
+ bugfix/arm/ARM-orion5x-Fix-GPIO-enable-bits-for-MPP9.patch
|
||||
|
||||
# Update all Hyper-V drivers to 3.4-rc1 (no longer staging)
|
||||
|
@ -96,8 +95,6 @@
|
|||
+ features/x86/hyperv/0076-net-hyperv-Fix-the-code-handling-tx-busy.patch
|
||||
+ features/x86/hyperv/0077-hv-remove-the-second-argument-of-k-un-map_atomic.patch
|
||||
|
||||
+ bugfix/all/hugetlb-fix-race-condition-in-hugetlb_fault.patch
|
||||
|
||||
+ features/x86/efi-stub/0011-x86-efi-Fix-pointer-math-issue-in-handle_ramdisks.patch
|
||||
+ features/x86/efi-stub/0012-tools-include-Add-byteshift-headers-for-endian-acces.patch
|
||||
+ features/x86/efi-stub/0013-x86-mkpiggy-Don-t-open-code-put_unaligned_le32.patch
|
||||
|
|
Loading…
Reference in New Issue