Commit 3a3527b6 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'core-rcu-for-linus' of...

Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  Revert "net: Make accesses to ->br_port safe for sparse RCU"
  mce: convert to rcu_dereference_index_check()
  net: Make accesses to ->br_port safe for sparse RCU
  vfs: add fs.h to define struct file
  lockdep: Add an in_workqueue_context() lockdep-based test function
  rcu: add __rcu API for later sparse checking
  rcu: add an rcu_dereference_index_check()
  tree/tiny rcu: Add debug RCU head objects
  mm: remove all rcu head initializations
  fs: remove all rcu head initializations, except on_stack initializations
  powerpc: remove all rcu head initializations
parents cc77b4db a53f4b61
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
static DEFINE_MUTEX(mce_read_mutex); static DEFINE_MUTEX(mce_read_mutex);
#define rcu_dereference_check_mce(p) \ #define rcu_dereference_check_mce(p) \
rcu_dereference_check((p), \ rcu_dereference_index_check((p), \
rcu_read_lock_sched_held() || \ rcu_read_lock_sched_held() || \
lockdep_is_held(&mce_read_mutex)) lockdep_is_held(&mce_read_mutex))
......
...@@ -178,7 +178,6 @@ static struct fdtable * alloc_fdtable(unsigned int nr) ...@@ -178,7 +178,6 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
fdt->open_fds = (fd_set *)data; fdt->open_fds = (fd_set *)data;
data += nr / BITS_PER_BYTE; data += nr / BITS_PER_BYTE;
fdt->close_on_exec = (fd_set *)data; fdt->close_on_exec = (fd_set *)data;
INIT_RCU_HEAD(&fdt->rcu);
fdt->next = NULL; fdt->next = NULL;
return fdt; return fdt;
...@@ -312,7 +311,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) ...@@ -312,7 +311,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
new_fdt->close_on_exec = (fd_set *)&newf->close_on_exec_init; new_fdt->close_on_exec = (fd_set *)&newf->close_on_exec_init;
new_fdt->open_fds = (fd_set *)&newf->open_fds_init; new_fdt->open_fds = (fd_set *)&newf->open_fds_init;
new_fdt->fd = &newf->fd_array[0]; new_fdt->fd = &newf->fd_array[0];
INIT_RCU_HEAD(&new_fdt->rcu);
new_fdt->next = NULL; new_fdt->next = NULL;
spin_lock(&oldf->file_lock); spin_lock(&oldf->file_lock);
...@@ -430,7 +428,6 @@ struct files_struct init_files = { ...@@ -430,7 +428,6 @@ struct files_struct init_files = {
.fd = &init_files.fd_array[0], .fd = &init_files.fd_array[0],
.close_on_exec = (fd_set *)&init_files.close_on_exec_init, .close_on_exec = (fd_set *)&init_files.close_on_exec_init,
.open_fds = (fd_set *)&init_files.open_fds_init, .open_fds = (fd_set *)&init_files.open_fds_init,
.rcu = RCU_HEAD_INIT,
}, },
.file_lock = __SPIN_LOCK_UNLOCKED(init_task.file_lock), .file_lock = __SPIN_LOCK_UNLOCKED(init_task.file_lock),
}; };
......
...@@ -459,7 +459,6 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, ...@@ -459,7 +459,6 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno,
} }
/* everything is up and running, commence */ /* everything is up and running, commence */
INIT_RCU_HEAD(&p->rcu_head);
rcu_assign_pointer(ptbl->part[partno], p); rcu_assign_pointer(ptbl->part[partno], p);
/* suppress uevent if the disk supresses it */ /* suppress uevent if the disk supresses it */
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
# define __release(x) __context__(x,-1) # define __release(x) __context__(x,-1)
# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0) # define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0)
# define __percpu __attribute__((noderef, address_space(3))) # define __percpu __attribute__((noderef, address_space(3)))
# define __rcu
extern void __chk_user_ptr(const volatile void __user *); extern void __chk_user_ptr(const volatile void __user *);
extern void __chk_io_ptr(const volatile void __iomem *); extern void __chk_io_ptr(const volatile void __iomem *);
#else #else
...@@ -34,6 +35,7 @@ extern void __chk_io_ptr(const volatile void __iomem *); ...@@ -34,6 +35,7 @@ extern void __chk_io_ptr(const volatile void __iomem *);
# define __release(x) (void)0 # define __release(x) (void)0
# define __cond_lock(x,c) (c) # define __cond_lock(x,c) (c)
# define __percpu # define __percpu
# define __rcu
#endif #endif
#ifdef __KERNEL__ #ifdef __KERNEL__
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/fs.h>
#include <asm/atomic.h> #include <asm/atomic.h>
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <linux/seqlock.h> #include <linux/seqlock.h>
#include <linux/lockdep.h> #include <linux/lockdep.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/debugobjects.h>
#ifdef CONFIG_RCU_TORTURE_TEST #ifdef CONFIG_RCU_TORTURE_TEST
extern int rcutorture_runnable; /* for sysctl */ extern int rcutorture_runnable; /* for sysctl */
...@@ -79,6 +80,16 @@ extern void rcu_init(void); ...@@ -79,6 +80,16 @@ extern void rcu_init(void);
(ptr)->next = NULL; (ptr)->func = NULL; \ (ptr)->next = NULL; (ptr)->func = NULL; \
} while (0) } while (0)
/*
* init_rcu_head_on_stack()/destroy_rcu_head_on_stack() are needed for dynamic
* initialization and destruction of rcu_head on the stack. rcu_head structures
* allocated dynamically in the heap or defined statically don't need any
* initialization.
*/
#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
extern void init_rcu_head_on_stack(struct rcu_head *head);
extern void destroy_rcu_head_on_stack(struct rcu_head *head);
#else /* !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
static inline void init_rcu_head_on_stack(struct rcu_head *head) static inline void init_rcu_head_on_stack(struct rcu_head *head)
{ {
} }
...@@ -86,6 +97,7 @@ static inline void init_rcu_head_on_stack(struct rcu_head *head) ...@@ -86,6 +97,7 @@ static inline void init_rcu_head_on_stack(struct rcu_head *head)
static inline void destroy_rcu_head_on_stack(struct rcu_head *head) static inline void destroy_rcu_head_on_stack(struct rcu_head *head)
{ {
} }
#endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
#ifdef CONFIG_DEBUG_LOCK_ALLOC #ifdef CONFIG_DEBUG_LOCK_ALLOC
...@@ -517,4 +529,74 @@ extern void call_rcu(struct rcu_head *head, ...@@ -517,4 +529,74 @@ extern void call_rcu(struct rcu_head *head,
extern void call_rcu_bh(struct rcu_head *head, extern void call_rcu_bh(struct rcu_head *head,
void (*func)(struct rcu_head *head)); void (*func)(struct rcu_head *head));
/*
* debug_rcu_head_queue()/debug_rcu_head_unqueue() are used internally
* by call_rcu() and rcu callback execution, and are therefore not part of the
* RCU API. Leaving in rcupdate.h because they are used by all RCU flavors.
*/
#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
# define STATE_RCU_HEAD_READY 0
# define STATE_RCU_HEAD_QUEUED 1
extern struct debug_obj_descr rcuhead_debug_descr;
static inline void debug_rcu_head_queue(struct rcu_head *head)
{
debug_object_activate(head, &rcuhead_debug_descr);
debug_object_active_state(head, &rcuhead_debug_descr,
STATE_RCU_HEAD_READY,
STATE_RCU_HEAD_QUEUED);
}
static inline void debug_rcu_head_unqueue(struct rcu_head *head)
{
debug_object_active_state(head, &rcuhead_debug_descr,
STATE_RCU_HEAD_QUEUED,
STATE_RCU_HEAD_READY);
debug_object_deactivate(head, &rcuhead_debug_descr);
}
#else /* !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
static inline void debug_rcu_head_queue(struct rcu_head *head)
{
}
static inline void debug_rcu_head_unqueue(struct rcu_head *head)
{
}
#endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
#ifndef CONFIG_PROVE_RCU
#define __do_rcu_dereference_check(c) do { } while (0)
#endif /* #ifdef CONFIG_PROVE_RCU */
#define __rcu_dereference_index_check(p, c) \
({ \
typeof(p) _________p1 = ACCESS_ONCE(p); \
__do_rcu_dereference_check(c); \
smp_read_barrier_depends(); \
(_________p1); \
})
/**
* rcu_dereference_index_check() - rcu_dereference for indices with debug checking
* @p: The pointer to read, prior to dereferencing
* @c: The conditions under which the dereference will take place
*
* Similar to rcu_dereference_check(), but omits the sparse checking.
* This allows rcu_dereference_index_check() to be used on integers,
* which can then be used as array indices. Attempting to use
* rcu_dereference_check() on an integer will give compiler warnings
* because the sparse address-space mechanism relies on dereferencing
* the RCU-protected pointer. Dereferencing integers is not something
* that even gcc will put up with.
*
* Note that this function does not implicitly check for RCU read-side
* critical sections. If this function gains lots of uses, it might
* make sense to provide versions for each flavor of RCU, but it does
* not make sense as of early 2010.
*/
#define rcu_dereference_index_check(p, c) \
__rcu_dereference_index_check((p), (c))
#endif /* __LINUX_RCUPDATE_H */ #endif /* __LINUX_RCUPDATE_H */
...@@ -297,4 +297,8 @@ static inline long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg) ...@@ -297,4 +297,8 @@ static inline long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg)
#else #else
long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg); long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg);
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
#ifdef CONFIG_LOCKDEP
int in_workqueue_context(struct workqueue_struct *wq);
#endif
#endif #endif
...@@ -114,3 +114,163 @@ int rcu_my_thread_group_empty(void) ...@@ -114,3 +114,163 @@ int rcu_my_thread_group_empty(void)
} }
EXPORT_SYMBOL_GPL(rcu_my_thread_group_empty); EXPORT_SYMBOL_GPL(rcu_my_thread_group_empty);
#endif /* #ifdef CONFIG_PROVE_RCU */ #endif /* #ifdef CONFIG_PROVE_RCU */
#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
static inline void debug_init_rcu_head(struct rcu_head *head)
{
debug_object_init(head, &rcuhead_debug_descr);
}
static inline void debug_rcu_head_free(struct rcu_head *head)
{
debug_object_free(head, &rcuhead_debug_descr);
}
/*
* fixup_init is called when:
* - an active object is initialized
*/
static int rcuhead_fixup_init(void *addr, enum debug_obj_state state)
{
struct rcu_head *head = addr;
switch (state) {
case ODEBUG_STATE_ACTIVE:
/*
* Ensure that queued callbacks are all executed.
* If we detect that we are nested in a RCU read-side critical
* section, we should simply fail, otherwise we would deadlock.
*/
if (rcu_preempt_depth() != 0 || preempt_count() != 0 ||
irqs_disabled()) {
WARN_ON(1);
return 0;
}
rcu_barrier();
rcu_barrier_sched();
rcu_barrier_bh();
debug_object_init(head, &rcuhead_debug_descr);
return 1;
default:
return 0;
}
}
/*
* fixup_activate is called when:
* - an active object is activated
* - an unknown object is activated (might be a statically initialized object)
* Activation is performed internally by call_rcu().
*/
static int rcuhead_fixup_activate(void *addr, enum debug_obj_state state)
{
struct rcu_head *head = addr;
switch (state) {
case ODEBUG_STATE_NOTAVAILABLE:
/*
* This is not really a fixup. We just make sure that it is
* tracked in the object tracker.
*/
debug_object_init(head, &rcuhead_debug_descr);
debug_object_activate(head, &rcuhead_debug_descr);
return 0;
case ODEBUG_STATE_ACTIVE:
/*
* Ensure that queued callbacks are all executed.
* If we detect that we are nested in a RCU read-side critical
* section, we should simply fail, otherwise we would deadlock.
*/
if (rcu_preempt_depth() != 0 || preempt_count() != 0 ||
irqs_disabled()) {
WARN_ON(1);
return 0;
}
rcu_barrier();
rcu_barrier_sched();
rcu_barrier_bh();
debug_object_activate(head, &rcuhead_debug_descr);
return 1;
default:
return 0;
}
}
/*
* fixup_free is called when:
* - an active object is freed
*/
static int rcuhead_fixup_free(void *addr, enum debug_obj_state state)
{
struct rcu_head *head = addr;
switch (state) {
case ODEBUG_STATE_ACTIVE:
/*
* Ensure that queued callbacks are all executed.
* If we detect that we are nested in a RCU read-side critical
* section, we should simply fail, otherwise we would deadlock.
*/
#ifndef CONFIG_PREEMPT
WARN_ON(1);
return 0;
#else
if (rcu_preempt_depth() != 0 || preempt_count() != 0 ||
irqs_disabled()) {
WARN_ON(1);
return 0;
}
rcu_barrier();
rcu_barrier_sched();
rcu_barrier_bh();
debug_object_free(head, &rcuhead_debug_descr);
return 1;
#endif
default:
return 0;
}
}
/**
* init_rcu_head_on_stack() - initialize on-stack rcu_head for debugobjects
* @head: pointer to rcu_head structure to be initialized
*
* This function informs debugobjects of a new rcu_head structure that
* has been allocated as an auto variable on the stack. This function
* is not required for rcu_head structures that are statically defined or
* that are dynamically allocated on the heap. This function has no
* effect for !CONFIG_DEBUG_OBJECTS_RCU_HEAD kernel builds.
*/
void init_rcu_head_on_stack(struct rcu_head *head)
{
debug_object_init_on_stack(head, &rcuhead_debug_descr);
}
EXPORT_SYMBOL_GPL(init_rcu_head_on_stack);
/**
* destroy_rcu_head_on_stack() - destroy on-stack rcu_head for debugobjects
* @head: pointer to rcu_head structure to be initialized
*
* This function informs debugobjects that an on-stack rcu_head structure
* is about to go out of scope. As with init_rcu_head_on_stack(), this
* function is not required for rcu_head structures that are statically
* defined or that are dynamically allocated on the heap. Also as with
* init_rcu_head_on_stack(), this function has no effect for
* !CONFIG_DEBUG_OBJECTS_RCU_HEAD kernel builds.
*/
void destroy_rcu_head_on_stack(struct rcu_head *head)
{
debug_object_free(head, &rcuhead_debug_descr);
}
EXPORT_SYMBOL_GPL(destroy_rcu_head_on_stack);
struct debug_obj_descr rcuhead_debug_descr = {
.name = "rcu_head",
.fixup_init = rcuhead_fixup_init,
.fixup_activate = rcuhead_fixup_activate,
.fixup_free = rcuhead_fixup_free,
};
EXPORT_SYMBOL_GPL(rcuhead_debug_descr);
#endif /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
...@@ -169,6 +169,7 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp) ...@@ -169,6 +169,7 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp)
while (list) { while (list) {
next = list->next; next = list->next;
prefetch(next); prefetch(next);
debug_rcu_head_unqueue(list);
list->func(list); list->func(list);
list = next; list = next;
} }
...@@ -211,6 +212,7 @@ static void __call_rcu(struct rcu_head *head, ...@@ -211,6 +212,7 @@ static void __call_rcu(struct rcu_head *head,
{ {
unsigned long flags; unsigned long flags;
debug_rcu_head_queue(head);
head->func = func; head->func = func;
head->next = NULL; head->next = NULL;
......
...@@ -1112,6 +1112,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp) ...@@ -1112,6 +1112,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
while (list) { while (list) {
next = list->next; next = list->next;
prefetch(next); prefetch(next);
debug_rcu_head_unqueue(list);
list->func(list); list->func(list);
list = next; list = next;
if (++count >= rdp->blimit) if (++count >= rdp->blimit)
...@@ -1388,6 +1389,7 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu), ...@@ -1388,6 +1389,7 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
unsigned long flags; unsigned long flags;
struct rcu_data *rdp; struct rcu_data *rdp;
debug_rcu_head_queue(head);
head->func = func; head->func = func;
head->next = NULL; head->next = NULL;
......
...@@ -68,6 +68,21 @@ struct workqueue_struct { ...@@ -68,6 +68,21 @@ struct workqueue_struct {
#endif #endif
}; };
#ifdef CONFIG_LOCKDEP
/**
* in_workqueue_context() - in context of specified workqueue?
* @wq: the workqueue of interest
*
* Checks lockdep state to see if the current task is executing from
* within a workqueue item. This function exists only if lockdep is
* enabled.
*/
int in_workqueue_context(struct workqueue_struct *wq)
{
return lock_is_held(&wq->lockdep_map);
}
#endif
#ifdef CONFIG_DEBUG_OBJECTS_WORK #ifdef CONFIG_DEBUG_OBJECTS_WORK
static struct debug_obj_descr work_debug_descr; static struct debug_obj_descr work_debug_descr;
......
...@@ -307,6 +307,12 @@ config DEBUG_OBJECTS_WORK ...@@ -307,6 +307,12 @@ config DEBUG_OBJECTS_WORK
work queue routines to track the life time of work objects and work queue routines to track the life time of work objects and
validate the work operations. validate the work operations.
config DEBUG_OBJECTS_RCU_HEAD
bool "Debug RCU callbacks objects"
depends on DEBUG_OBJECTS && PREEMPT
help
Enable this to turn on debugging of RCU list heads (call_rcu() usage).
config DEBUG_OBJECTS_ENABLE_DEFAULT config DEBUG_OBJECTS_ENABLE_DEFAULT
int "debug_objects bootup default value (0-1)" int "debug_objects bootup default value (0-1)"
range 0 1 range 0 1
......
...@@ -665,7 +665,6 @@ int bdi_init(struct backing_dev_info *bdi) ...@@ -665,7 +665,6 @@ int bdi_init(struct backing_dev_info *bdi)
bdi->max_ratio = 100; bdi->max_ratio = 100;
bdi->max_prop_frac = PROP_FRAC_BASE; bdi->max_prop_frac = PROP_FRAC_BASE;
spin_lock_init(&bdi->wb_lock); spin_lock_init(&bdi->wb_lock);
INIT_RCU_HEAD(&bdi->rcu_head);
INIT_LIST_HEAD(&bdi->bdi_list); INIT_LIST_HEAD(&bdi->bdi_list);
INIT_LIST_HEAD(&bdi->wb_list); INIT_LIST_HEAD(&bdi->wb_list);
INIT_LIST_HEAD(&bdi->work_list); INIT_LIST_HEAD(&bdi->work_list);
......
...@@ -639,7 +639,6 @@ void kmem_cache_free(struct kmem_cache *c, void *b) ...@@ -639,7 +639,6 @@ void kmem_cache_free(struct kmem_cache *c, void *b)
if (unlikely(c->flags & SLAB_DESTROY_BY_RCU)) { if (unlikely(c->flags & SLAB_DESTROY_BY_RCU)) {
struct slob_rcu *slob_rcu; struct slob_rcu *slob_rcu;
slob_rcu = b + (c->size - sizeof(struct slob_rcu)); slob_rcu = b + (c->size - sizeof(struct slob_rcu));
INIT_RCU_HEAD(&slob_rcu->head);
slob_rcu->size = c->size; slob_rcu->size = c->size;
call_rcu(&slob_rcu->head, kmem_rcu_free); call_rcu(&slob_rcu->head, kmem_rcu_free);
} else { } else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment