public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Re: Question about (or bug in?) the kobject implementation
@ 2004-02-28  4:02 Alan Stern
  2004-02-28  7:38 ` Michael Frank
  2004-03-03 21:44 ` Greg KH
  0 siblings, 2 replies; 10+ messages in thread
From: Alan Stern @ 2004-02-28  4:02 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel

On Fri, 27 Feb 2004, Greg KH wrote:

> Seriously, once kobject_del() is called, you can't safely call
> kobject_get() anymore on that object.
> 
> If you can think of a way we can implement this in the code to prevent
> people from doing this, please send a patch.  We've been getting by
> without such a "safeguard" so far...

The problem is unsolvable.  Let me explain...

We're actually discussing two different questions here.

    A.	Is it okay to call kobject_add() after calling kobject_del() -- 
	this was my original question.

    B.	Can we prevent people from doing kobject_get() after the kobject's
	refcount has dropped to 0?

Your earlier response amounted to saying that A isn't good because it
might cause B to happen; once kobject_del() has returned it's possible
that the refcount is 0.  But this begs the real question.  Suppose we
_know_ that the refcount isn't 0, say because earlier we did an unmatched
kobject_get().  Under those circumstances should it be legal to call
kobject_add() after calling kobject_del()?  This is question A'.


Question B can be divided into two subcases.

    B1.	The code calling kobject_get() knows that the kobject hasn't been
	deallocated yet.  For example, it might be the cleanup routine 
	itself calling kobject_get().

Such a thing is legal in Java, but you probably don't want to sanction 
such pranks in the driver model.  So let's forget about B1.  Your big 
concern really seems to be:

    B2.	Everything else; the code calling kobject_get() doesn't know 
	whether the kobject has been deallocated.

This really is a programming error.  It means that kobject_get() has been 
passed a possibly stale pointer.  Ipso facto, the call to kobject_put() 
that decremented the refcount to 0 was made too early, while there were 
still active pointers to the kobject floating around.

It's impossible to prevent people from making programming errors or
dereferencing stale pointers.  It doesn't matter _what_ code you put in
kobject_get() -- it will crash when given a pointer to a kobject whose
cleanup routine has already run and deallocated the storage.

The best you can do is call people's attention to such errors and fail the
operation gracefully whenever possible (i.e., when it doesn't generate an
addressing error).  My personal choice would be to change kobject_get() as
follows:

struct kobject * kobject_get(struct kobject * kobj)
{
	if (kobj) {
		if (atomic_read(&kobj->refcount) == 0) {
			WARN_ON(1);
			return NULL;
		}
		atomic_inc(&kobj->refcount);
	}
	return kobj;
}

I think that's about the best you can do.

And what's the answer to A'?

Alan Stern


^ permalink raw reply	[flat|nested] 10+ messages in thread
* Question about (or bug in?) the kobject implementation
@ 2004-02-25 15:05 Alan Stern
  2004-02-27 19:48 ` Greg KH
  0 siblings, 1 reply; 10+ messages in thread
From: Alan Stern @ 2004-02-25 15:05 UTC (permalink / raw)
  To: Kernel development list

Is it supposed to be legal to repeatedly call kobject_add() and 
kobject_del() for the same kobject?  That is, is

	kobject_add(&kobj);
	...
	kobject_del(&kobj);
	...
	kobject_add(&kobj);
	...
	kobject_del(&kobj);

supposed to work?  The API doesn't forbid it, and there's no apparent 
reason why it should be illegal.

I ask because the current implementation is set up in such a way that
doing this will mess up the reference counting for the kobject's parent.  
The problem is that the parent's refcount is increased each time
kobject_add() is called, but it is only decremented in kobject_cleanup(),
not in kobject_del().  Thus, the statements above will leave the parent's
refcount permanently increased by 1, potentially causing a memory leak.

Why would anyone want to do this, you ask?  Well the USB subsystem does it 
already.  Each USB device can have several configurations, only one of 
which is active at any time.  Corresponding to each configuration is a set 
of struct devices, and they (together with their embedded kobjects) are 
allocated and initialized when the USB device is first detected.  The 
struct devices are add()'ed and del()'ed as configurations are activated 
and deactivated, leading to just the sort of call sequence shown above.

Alan Stern


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2004-03-03 22:17 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-02-28  4:02 Question about (or bug in?) the kobject implementation Alan Stern
2004-02-28  7:38 ` Michael Frank
2004-02-28 17:09   ` Alan Stern
2004-03-03 21:44 ` Greg KH
2004-03-03 22:11   ` Alan Stern
2004-03-03 22:16     ` Greg KH
  -- strict thread matches above, loose matches on Subject: below --
2004-02-25 15:05 Alan Stern
2004-02-27 19:48 ` Greg KH
2004-02-27 20:06   ` Alan Stern
2004-02-27 20:17     ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox