It is sometimes useful to get the value of the reference count after decrement. For example, vhost wants to execute some periodic cleanup operations once number of references drops below a specific value, before it reaches zero (for efficiency).
Add an API to do this atomically and efficiently using atomic_sub_return. Signed-off-by: Michael S. Tsirkin <m...@redhat.com> --- Greg, could you ack this API extension please? I think it is cleanest to merge this through -net together with the first user. include/linux/kref.h | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/include/linux/kref.h b/include/linux/kref.h index 484604d..cb20550 100644 --- a/include/linux/kref.h +++ b/include/linux/kref.h @@ -61,7 +61,7 @@ static inline void kref_get(struct kref *kref) * * Subtract @count from the refcount, and if 0, call release(). * Return 1 if the object was removed, otherwise return 0. Beware, if this - * function returns 0, you still can not count on the kref from remaining in + * function returns 0, you still can not count on the kref remaining in * memory. Only use the return value if you want to see if the kref is now * gone, not present. */ @@ -78,6 +78,38 @@ static inline int kref_sub(struct kref *kref, unsigned int count, } /** + * kref_sub_return - subtract a number of refcounts for object. + * @kref: object. + * @count: Number of recounts to subtract. + * @release: pointer to the function that will clean up the object when the + * last reference to the object is released. + * This pointer is required, and it is not acceptable to pass kfree + * in as this function. If the caller does pass kfree to this + * function, you will be publicly mocked mercilessly by the kref + * maintainer, and anyone else who happens to notice it. You have + * been warned. + * + * Subtract @count from the refcount, and if 0, call release(). + * Return the new refcount. Beware, if this function returns > N, you still + * can not count on there being at least N other references, and in + * particular, on the kref remaining in memory. + * Only use the return value if you want to see if there are at most, + * not at least, N other references to kref, + */ +static inline int kref_sub_return(struct kref *kref, unsigned int count, + void (*release)(struct kref *kref)) +{ + int r; + + WARN_ON(release == NULL); + + r = atomic_sub_return((int) count, &kref->refcount); + if (!r) + release(kref); + return r; +} + +/** * kref_put - decrement refcount for object. * @kref: object. * @release: pointer to the function that will clean up the object when the -- MST -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/