From: Peter Zijlstra on
On Tue, 2010-04-20 at 16:23 +0800, Lai Jiangshan wrote:
>
> One variable per usage, so, Now, we can get multiple complaint
> when we detect multiple different suspicious rcu_dereference_check()
> usage.
>

Ah indeed, very nice.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Eric Paris on
On Tue, 2010-04-20 at 16:23 +0800, Lai Jiangshan wrote:

> [PATCH] RCU: don't turn off lockdep when find suspicious rcu_dereference_check() usage
>
> When suspicious rcu_dereference_check() usage is detected, lockdep is still
> available actually, so we should not call debug_locks_off() in
> lockdep_rcu_dereference().
>
> For get rid of too much "suspicious rcu_dereference_check() usage"
> output when the "if(!debug_locks_off())" statement is removed. This patch uses
> static variable '__warned's for very usage of "rcu_dereference*()".
>
> One variable per usage, so, Now, we can get multiple complaint
> when we detect multiple different suspicious rcu_dereference_check() usage.
>
> Requested-by: Eric Paris <eparis(a)redhat.com>
> Signed-off-by: Lai Jiangshan <laijs(a)cn.fujitsu.com>

Although mine was a linux-next kernel and it doesn't appear that I have
rcu_dereference_protected() at all, so I dropped that bit of the patch,
it worked great! I got 4 more complaints to harass people with. Feel
free to add my tested by if you care to.

Tested-by: Eric Paris <eparis(a)redhat.com>

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Paul E. McKenney on
On Tue, Apr 20, 2010 at 08:31:56AM -0400, Eric Paris wrote:
> On Tue, 2010-04-20 at 16:23 +0800, Lai Jiangshan wrote:
>
> > [PATCH] RCU: don't turn off lockdep when find suspicious rcu_dereference_check() usage
> >
> > When suspicious rcu_dereference_check() usage is detected, lockdep is still
> > available actually, so we should not call debug_locks_off() in
> > lockdep_rcu_dereference().
> >
> > For get rid of too much "suspicious rcu_dereference_check() usage"
> > output when the "if(!debug_locks_off())" statement is removed. This patch uses
> > static variable '__warned's for very usage of "rcu_dereference*()".
> >
> > One variable per usage, so, Now, we can get multiple complaint
> > when we detect multiple different suspicious rcu_dereference_check() usage.
> >
> > Requested-by: Eric Paris <eparis(a)redhat.com>
> > Signed-off-by: Lai Jiangshan <laijs(a)cn.fujitsu.com>
>
> Although mine was a linux-next kernel and it doesn't appear that I have
> rcu_dereference_protected() at all, so I dropped that bit of the patch,
> it worked great! I got 4 more complaints to harass people with. Feel
> free to add my tested by if you care to.
>
> Tested-by: Eric Paris <eparis(a)redhat.com>

Very nice!!! Queued for urgent, thank you Lai and Eric!!!

Thanx, Paul
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Paul E. McKenney on
On Tue, Apr 20, 2010 at 08:45:28AM -0400, Miles Lane wrote:
> Is there a patch set for 2.6.34-rc5 I can test?

I will be sending a patchset out later today after testing, but
please see below for a sneak preview collapsed into a single patch.

Thanx, Paul

> On Tue, Apr 20, 2010 at 8:31 AM, Eric Paris <eparis(a)redhat.com> wrote:
>
> > On Tue, 2010-04-20 at 16:23 +0800, Lai Jiangshan wrote:
> >
> > > [PATCH] RCU: don't turn off lockdep when find suspicious
> > rcu_dereference_check() usage
> > >
> > > When suspicious rcu_dereference_check() usage is detected, lockdep is
> > still
> > > available actually, so we should not call debug_locks_off() in
> > > lockdep_rcu_dereference().
> > >
> > > For get rid of too much "suspicious rcu_dereference_check() usage"
> > > output when the "if(!debug_locks_off())" statement is removed. This patch
> > uses
> > > static variable '__warned's for very usage of "rcu_dereference*()".
> > >
> > > One variable per usage, so, Now, we can get multiple complaint
> > > when we detect multiple different suspicious rcu_dereference_check()
> > usage.
> > >
> > > Requested-by: Eric Paris <eparis(a)redhat.com>
> > > Signed-off-by: Lai Jiangshan <laijs(a)cn.fujitsu.com>
> >
> > Although mine was a linux-next kernel and it doesn't appear that I have
> > rcu_dereference_protected() at all, so I dropped that bit of the patch,
> > it worked great! I got 4 more complaints to harass people with. Feel
> > free to add my tested by if you care to.
> >
> > Tested-by: Eric Paris <eparis(a)redhat.com>

diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 07db2fe..ec9ab49 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -190,6 +190,15 @@ static inline int rcu_read_lock_sched_held(void)

#ifdef CONFIG_PROVE_RCU

+#define __do_rcu_dereference_check(c) \
+ do { \
+ static bool __warned; \
+ if (debug_lockdep_rcu_enabled() && !__warned && !(c)) { \
+ __warned = true; \
+ lockdep_rcu_dereference(__FILE__, __LINE__); \
+ } \
+ } while (0)
+
/**
* rcu_dereference_check - rcu_dereference with debug checking
* @p: The pointer to read, prior to dereferencing
@@ -219,8 +228,7 @@ static inline int rcu_read_lock_sched_held(void)
*/
#define rcu_dereference_check(p, c) \
({ \
- if (debug_lockdep_rcu_enabled() && !(c)) \
- lockdep_rcu_dereference(__FILE__, __LINE__); \
+ __do_rcu_dereference_check(c); \
rcu_dereference_raw(p); \
})

@@ -237,8 +245,7 @@ static inline int rcu_read_lock_sched_held(void)
*/
#define rcu_dereference_protected(p, c) \
({ \
- if (debug_lockdep_rcu_enabled() && !(c)) \
- lockdep_rcu_dereference(__FILE__, __LINE__); \
+ __do_rcu_dereference_check(c); \
(p); \
})

diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c
index da5e139..e5c0244 100644
--- a/kernel/cgroup_freezer.c
+++ b/kernel/cgroup_freezer.c
@@ -205,9 +205,12 @@ static void freezer_fork(struct cgroup_subsys *ss, struct task_struct *task)
* No lock is needed, since the task isn't on tasklist yet,
* so it can't be moved to another cgroup, which means the
* freezer won't be removed and will be valid during this
- * function call.
+ * function call. Nevertheless, apply RCU read-side critical
+ * section to suppress RCU lockdep false positives.
*/
+ rcu_read_lock();
freezer = task_freezer(task);
+ rcu_read_unlock();

/*
* The root cgroup is non-freezable, so we can skip the
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 2594e1c..03dd1fa 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -3801,8 +3801,6 @@ void lockdep_rcu_dereference(const char *file, const int line)
{
struct task_struct *curr = current;

- if (!debug_locks_off())
- return;
printk("\n===================================================\n");
printk( "[ INFO: suspicious rcu_dereference_check() usage. ]\n");
printk( "---------------------------------------------------\n");
diff --git a/kernel/sched.c b/kernel/sched.c
index 6af210a..14c44ec 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -323,6 +323,15 @@ static inline struct task_group *task_group(struct task_struct *p)
/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
{
+ /*
+ * Strictly speaking this rcu_read_lock() is not needed since the
+ * task_group is tied to the cgroup, which in turn can never go away
+ * as long as there are tasks attached to it.
+ *
+ * However since task_group() uses task_subsys_state() which is an
+ * rcu_dereference() user, this quiets CONFIG_PROVE_RCU.
+ */
+ rcu_read_lock();
#ifdef CONFIG_FAIR_GROUP_SCHED
p->se.cfs_rq = task_group(p)->cfs_rq[cpu];
p->se.parent = task_group(p)->se[cpu];
@@ -332,6 +341,7 @@ static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
p->rt.rt_rq = task_group(p)->rt_rq[cpu];
p->rt.parent = task_group(p)->rt_se[cpu];
#endif
+ rcu_read_unlock();
}

#else
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Paul E. McKenney on
On Thu, Apr 22, 2010 at 10:56:40AM -0400, Vivek Goyal wrote:
> On Wed, Apr 21, 2010 at 02:35:43PM -0700, Paul E. McKenney wrote:
>
> [..]
> > > [ 3.116754] [ INFO: suspicious rcu_dereference_check() usage. ]
> > > [ 3.116754] ---------------------------------------------------
> > > [ 3.116754] kernel/cgroup.c:4432 invoked rcu_dereference_check()
> > > without protection!
> > > [ 3.116754]
> > > [ 3.116754] other info that might help us debug this:
> > > [ 3.116754]
> > > [ 3.116754]
> > > [ 3.116754] rcu_scheduler_active = 1, debug_locks = 1
> > > [ 3.116754] 2 locks held by async/1/666:
> > > [ 3.116754] #0: (&shost->scan_mutex){+.+.+.}, at:
> > > [<ffffffff812df0a0>] __scsi_add_device+0x83/0xe4
> > > [ 3.116754] #1: (&(&blkcg->lock)->rlock){......}, at:
> > > [<ffffffff811f2e8d>] blkiocg_add_blkio_group+0x29/0x7f
> > > [ 3.116754]
> > > [ 3.116754] stack backtrace:
> > > [ 3.116754] Pid: 666, comm: async/1 Not tainted 2.6.34-rc5 #18
> > > [ 3.116754] Call Trace:
> > > [ 3.116754] [<ffffffff81067fc2>] lockdep_rcu_dereference+0x9d/0xa5
> > > [ 3.116754] [<ffffffff8107f9b1>] css_id+0x3f/0x51
> > > [ 3.116754] [<ffffffff811f2e9c>] blkiocg_add_blkio_group+0x38/0x7f
> > > [ 3.116754] [<ffffffff811f4e64>] cfq_init_queue+0xdf/0x2dc
> > > [ 3.116754] [<ffffffff811e3445>] elevator_init+0xba/0xf5
> > > [ 3.116754] [<ffffffff812dc02a>] ? scsi_request_fn+0x0/0x451
> > > [ 3.116754] [<ffffffff811e696b>] blk_init_queue_node+0x12f/0x135
> > > [ 3.116754] [<ffffffff811e697d>] blk_init_queue+0xc/0xe
> > > [ 3.116754] [<ffffffff812dc49c>] __scsi_alloc_queue+0x21/0x111
> > > [ 3.116754] [<ffffffff812dc5a4>] scsi_alloc_queue+0x18/0x64
> > > [ 3.116754] [<ffffffff812de5a0>] scsi_alloc_sdev+0x19e/0x256
> > > [ 3.116754] [<ffffffff812de73e>] scsi_probe_and_add_lun+0xe6/0x9c5
> > > [ 3.116754] [<ffffffff81068922>] ? trace_hardirqs_on_caller+0x114/0x13f
> > > [ 3.116754] [<ffffffff813ce0d6>] ? __mutex_lock_common+0x3e4/0x43a
> > > [ 3.116754] [<ffffffff812df0a0>] ? __scsi_add_device+0x83/0xe4
> > > [ 3.116754] [<ffffffff812d0a5c>] ? transport_setup_classdev+0x0/0x17
> > > [ 3.116754] [<ffffffff812df0a0>] ? __scsi_add_device+0x83/0xe4
> > > [ 3.116754] [<ffffffff812df0d5>] __scsi_add_device+0xb8/0xe4
> > > [ 3.116754] [<ffffffff812ea9c5>] ata_scsi_scan_host+0x74/0x16e
> > > [ 3.116754] [<ffffffff81057685>] ? autoremove_wake_function+0x0/0x34
> > > [ 3.116754] [<ffffffff812e8e64>] async_port_probe+0xab/0xb7
> > > [ 3.116754] [<ffffffff8105e1b5>] ? async_thread+0x0/0x1f4
> > > [ 3.116754] [<ffffffff8105e2ba>] async_thread+0x105/0x1f4
> > > [ 3.116754] [<ffffffff81033d79>] ? default_wake_function+0x0/0xf
> > > [ 3.116754] [<ffffffff8105e1b5>] ? async_thread+0x0/0x1f4
> > > [ 3.116754] [<ffffffff8105713e>] kthread+0x89/0x91
> > > [ 3.116754] [<ffffffff81068922>] ? trace_hardirqs_on_caller+0x114/0x13f
> > > [ 3.116754] [<ffffffff81003994>] kernel_thread_helper+0x4/0x10
> > > [ 3.116754] [<ffffffff813cfcc0>] ? restore_args+0x0/0x30
> > > [ 3.116754] [<ffffffff810570b5>] ? kthread+0x0/0x91
> > > [ 3.116754] [<ffffffff81003990>] ? kernel_thread_helper+0x0/0x10
> >
> > I cannot convince myself that the above access is safe. Vivek, Nauman,
> > thoughts?
>
> Hi Paul,
>
> blkiocg_add_blkio_group() is called from two paths.
>
> First one is following. This path should be safe as it takes rcu read
> lock.
>
> cfq_get_cfqg()
> rcu_read_lock()
> cfq_find_alloc_cfqg()
> blkiocg_add_blkio_group()
> rcu_read_unlock()
>
> Second one is as shown in above backtrace.
>
> cfq_init_queue()
> blkiocg_add_blkio_group().
>
> This path is called at request queue and cfq initialization time and
> we access only root cgroup (root blkio_cgroup). As root cgroup can't
> go away, do we have to protect that call also using rcu_read_lock()?

You are correct, if the root cgroup cannot go away and if we only access
the root cgroup, then rcu_read_lock() is not required.

> So I guess it is not unsafe but propably we need to fix the warning, I
> should wrap second call to blkiocg_add_blkio_group() with
> rcu_read_lock/unlock pair?

That would work very well!

Thanx, Paul
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/