lu_ref

An interface to track references between objects. More...

Data Structures

struct  lu_ref

Detailed Description

An interface to track references between objects.

Mostly for debugging.

Suppose there is a reference counted data-structure struct foo. To track who acquired references to instance of struct foo, add lu_ref field to it:

         struct foo {
                 atomic_t      foo_refcount;
                 struct lu_ref foo_reference;
                 ...
         };

foo::foo_reference has to be initialized by calling lu_ref_init(). Typically there will be functions or macros to increment and decrement foo::foo_refcount, let's say they are foo_get(struct foo *foo) and foo_put(struct foo *foo), respectively.

Whenever foo_get() is called to acquire a reference on a foo, lu_ref_add() has to be called to insert into foo::foo_reference a record, describing acquired reference. Dually, lu_ref_del() removes matching record. Typical usages are:

        struct bar *bar;

        // bar owns a reference to foo.
        bar->bar_foo = foo_get(foo);
        lu_ref_add(&foo->foo_reference, "bar", bar);

        ...

        // reference from bar to foo is released.
        lu_ref_del(&foo->foo_reference, "bar", bar);
        foo_put(bar->bar_foo);


        // current thread acquired a temporary reference to foo.
        foo_get(foo);
        lu_ref_add(&foo->reference, __FUNCTION__, cfs_current());

        ...

        // temporary reference is released.
        lu_ref_del(&foo->reference, __FUNCTION__, cfs_current());
        foo_put(foo);

Et cetera. Often it makes sense to include lu_ref_add() and lu_ref_del() calls into foo_get() and foo_put(). When an instance of struct foo is destroyed, lu_ref_fini() has to be called that checks that no pending references remain. lu_ref_print() can be used to dump a list of pending references, while hunting down a leak.

For objects to which a large number of references can be acquired, lu_ref_del() can become cpu consuming, as it has to scan the list of references. To work around this, remember result of lu_ref_add() (usually in the same place where pointer to struct foo is stored), and use lu_ref_del_at():

        // There is a large number of bar's for a single foo.
        bar->bar_foo     = foo_get(foo);
        bar->bar_foo_ref = lu_ref_add(&foo->foo_reference, "bar", bar);

        ...

        // reference from bar to foo is released.
        lu_ref_del_at(&foo->foo_reference, bar->bar_foo_ref, "bar", bar);
        foo_put(bar->bar_foo);

lu_ref interface degrades gracefully in case of memory shortages.


Generated on Mon Apr 12 04:18:21 2010 for Lustre 1.10.0.40-0-g9a80ff7 by doxygen 1.4.7

Contact | About Sun | News | Employment | Privacy | Terms of Use | Trademarks | (C) 2008 Sun Microsystems, Inc.