[PATCH 2/4] utrace_reap: do not play with ->reporting
Oleg Nesterov
oleg at redhat.com
Tue Sep 8 18:39:20 UTC 2009
On 09/07, Roland McGrath wrote:
>
> > But more importantly, I think utrace_reap() never needs to synchronize
> > with utrace_barrier(). Once we drop utrace->lock, any other caller which
> > takes this lock must see both ->exit_state and utrace->reap. This means
> > utrace_control() or utrace_set_events() which sets/clears REAP must not
> > succeed.
>
> Right. So this doesn't matter for the primary original purpose of
> utrace_barrier, i.e.:
>
> * A successful return from utrace_barrier() guarantees its ordering
> * with respect to utrace_set_events() and utrace_control() calls.
Yes.
> But IMHO it would be nice (and the least surprising thing) if this
> statement were really true too:
>
> * A return value of zero means no callback from @target to @engine was
> * in progress.
I was going to write that this doesn't make real sense, but now I think
you are right. For example,
something_t *ptr;
void my_report_reap(...)
{
if (ptr)
dereference(ptr);
}
...
void *tmp = ptr;
ptr = NULL;
utrace_barrier(my_engine);
kfree(tmp);
With or without recent changes, this doesn't work.
> I'm not really sure about the barriers,
Me too.
In fact, recently I realized I don't really understand the barriers
around ->reporting, need to read this code with a fresh head. In
particular, I'd like to see
1. Can't we set ->reporting _after_ checking engine->flags ?
(unlikely)
2. Is utrace_barrier() correct???? Note the example above,
it assumes that utrace_barrier() itself is the barrier
wrt reporting. But, is it?
> list_for_each_entry_safe(engine, next, &utrace->attached, entry) {
> - if (engine->flags & UTRACE_EVENT(REAP))
> + if (engine->flags & UTRACE_EVENT(REAP)) {
> + /*
> + * These barriers order anything ->report_reap()
> + * does to be while ->reporting is set. That way
> + * any utrace_barrier() call that returns 0 is
> + * guaranteeing that the callback is complete.
> + */
> + utrace->reporting = engine;
> + smp_mb();
> engine->ops->report_reap(engine, target);
> + smp_mb();
> + utrace->reporting = NULL;
Agreed.
And yes, now it is important to clear ->ops _after_ calling
->report_reap(), otherwise utrace_barrier() can take the lock.
Oleg.
More information about the utrace-devel
mailing list