rpms/kernel/F-10 linux-2.6-lib-idr.c-fix-rcu-related-race-with-idr_find.patch, NONE, 1.1 kernel.spec, 1.1179, 1.1180
Chuck Ebbert
cebbert at fedoraproject.org
Tue Dec 9 12:55:51 UTC 2008
Author: cebbert
Update of /cvs/pkgs/rpms/kernel/F-10
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv19786
Modified Files:
kernel.spec
Added Files:
linux-2.6-lib-idr.c-fix-rcu-related-race-with-idr_find.patch
Log Message:
Revert idr patch from 2.6.27.8 that caused DRM breakage.
linux-2.6-lib-idr.c-fix-rcu-related-race-with-idr_find.patch:
--- NEW FILE linux-2.6-lib-idr.c-fix-rcu-related-race-with-idr_find.patch ---
>From 6ff2d39b91aec3dcae951afa982059e3dd9b49dc Mon Sep 17 00:00:00 2001
From: Manfred Spraul <manfred at colorfullife.com>
Date: Mon, 1 Dec 2008 13:14:02 -0800
Subject: lib/idr.c: fix rcu related race with idr_find
From: Manfred Spraul <manfred at colorfullife.com>
commit 6ff2d39b91aec3dcae951afa982059e3dd9b49dc upstream.
2nd part of the fixes needed for
http://bugzilla.kernel.org/show_bug.cgi?id=11796.
When the idr tree is either grown or shrunk, then the update to the number
of layers and the top pointer were not atomic. This race caused crashes.
The attached patch fixes that by replicating the layers counter in each
layer, thus idr_find doesn't need idp->layers anymore.
Signed-off-by: Manfred Spraul <manfred at colorfullife.com>
Cc: Clement Calmels <cboulte at gmail.com>
Cc: Nadia Derbey <Nadia.Derbey at bull.net>
Cc: Pierre Peiffer <peifferp at gmail.com>
Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
---
include/linux/idr.h | 3 ++-
lib/idr.c | 14 ++++++++++++--
2 files changed, 14 insertions(+), 3 deletions(-)
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -52,13 +52,14 @@ struct idr_layer {
unsigned long bitmap; /* A zero bit means "space here" */
struct idr_layer *ary[1<<IDR_BITS];
int count; /* When zero, we can release it */
+ int layer; /* distance from leaf */
struct rcu_head rcu_head;
};
struct idr {
struct idr_layer *top;
struct idr_layer *id_free;
- int layers;
+ int layers; /* only valid without concurrent changes */
int id_free_cnt;
spinlock_t lock;
};
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -185,6 +185,7 @@ static int sub_alloc(struct idr *idp, in
new = get_from_free_list(idp);
if (!new)
return -1;
+ new->layer = l-1;
rcu_assign_pointer(p->ary[m], new);
p->count++;
}
@@ -210,6 +211,7 @@ build_up:
if (unlikely(!p)) {
if (!(p = get_from_free_list(idp)))
return -1;
+ p->layer = 0;
layers = 1;
}
/*
@@ -237,6 +239,7 @@ build_up:
}
new->ary[0] = p;
new->count = 1;
+ new->layer = layers-1;
if (p->bitmap == IDR_FULL)
__set_bit(0, &new->bitmap);
p = new;
@@ -493,17 +496,21 @@ void *idr_find(struct idr *idp, int id)
int n;
struct idr_layer *p;
- n = idp->layers * IDR_BITS;
p = rcu_dereference(idp->top);
+ if (!p)
+ return NULL;
+ n = (p->layer+1) * IDR_BITS;
/* Mask off upper bits we don't use for the search. */
id &= MAX_ID_MASK;
if (id >= (1 << n))
return NULL;
+ BUG_ON(n == 0);
while (n > 0 && p) {
n -= IDR_BITS;
+ BUG_ON(n != p->layer*IDR_BITS);
p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]);
}
return((void *)p);
@@ -582,8 +589,11 @@ void *idr_replace(struct idr *idp, void
int n;
struct idr_layer *p, *old_p;
- n = idp->layers * IDR_BITS;
p = idp->top;
+ if (!p)
+ return ERR_PTR(-EINVAL);
+
+ n = (p->layer+1) * IDR_BITS;
id &= MAX_ID_MASK;
Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-10/kernel.spec,v
retrieving revision 1.1179
retrieving revision 1.1180
diff -u -r1.1179 -r1.1180
--- kernel.spec 9 Dec 2008 03:52:37 -0000 1.1179
+++ kernel.spec 9 Dec 2008 12:55:20 -0000 1.1180
@@ -575,6 +575,8 @@
%if !%{nopatches}
# revert upstream patches we get via other methods
+# revert 2.6.27.8 idr patch that breaks DRM
+Patch08: linux-2.6-lib-idr.c-fix-rcu-related-race-with-idr_find.patch
Patch09: linux-2.6-upstream-reverts.patch
# Git trees.
Patch10: git-cpufreq.patch
@@ -1085,6 +1087,9 @@
%if !%{nopatches}
+# revert IDR patch from 2.6.27.8
+ApplyPatch linux-2.6-lib-idr.c-fix-rcu-related-race-with-idr_find.patch -R
+
# revert patches from upstream that conflict or that we get via other means
C=$(wc -l $RPM_SOURCE_DIR/linux-2.6-upstream-reverts.patch | awk '{print $1}')
if [ "$C" -gt 10 ]; then
@@ -1911,6 +1916,9 @@
%kernel_variant_files -k vmlinux %{with_kdump} kdump
%changelog
+* Tue Dec 09 2008 Chuck Ebbert <cebbert at redhat.com> 2.6.27.8-144
+- Revert idr patch from 2.6.27.8 that caused DRM breakage.
+
* Mon Dec 08 2008 Chuck Ebbert <cebbert at redhat.com> 2.6.27.8-143
- ATM security fix (CVE-2008-5079)
More information about the fedora-extras-commits
mailing list