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:

Etcetera. 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);