194a312a1SFrançois Tigeot /*- 294a312a1SFrançois Tigeot * Copyright (c) 2010 Isilon Systems, Inc. 394a312a1SFrançois Tigeot * Copyright (c) 2010 iX Systems, Inc. 494a312a1SFrançois Tigeot * Copyright (c) 2010 Panasas, Inc. 5*a85cb24fSFrançois Tigeot * Copyright (c) 2013-2020 François Tigeot <ftigeot@wolfpond.org> 694a312a1SFrançois Tigeot * All rights reserved. 794a312a1SFrançois Tigeot * 894a312a1SFrançois Tigeot * Redistribution and use in source and binary forms, with or without 994a312a1SFrançois Tigeot * modification, are permitted provided that the following conditions 1094a312a1SFrançois Tigeot * are met: 1194a312a1SFrançois Tigeot * 1. Redistributions of source code must retain the above copyright 1294a312a1SFrançois Tigeot * notice unmodified, this list of conditions, and the following 1394a312a1SFrançois Tigeot * disclaimer. 1494a312a1SFrançois Tigeot * 2. Redistributions in binary form must reproduce the above copyright 1594a312a1SFrançois Tigeot * notice, this list of conditions and the following disclaimer in the 1694a312a1SFrançois Tigeot * documentation and/or other materials provided with the distribution. 1794a312a1SFrançois Tigeot * 1894a312a1SFrançois Tigeot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1994a312a1SFrançois Tigeot * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2094a312a1SFrançois Tigeot * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2194a312a1SFrançois Tigeot * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2294a312a1SFrançois Tigeot * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2394a312a1SFrançois Tigeot * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2494a312a1SFrançois Tigeot * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2594a312a1SFrançois Tigeot * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2694a312a1SFrançois Tigeot * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2794a312a1SFrançois Tigeot * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2894a312a1SFrançois Tigeot */ 2994a312a1SFrançois Tigeot #ifndef _LINUX_KREF_H_ 3094a312a1SFrançois Tigeot #define _LINUX_KREF_H_ 3194a312a1SFrançois Tigeot 32*a85cb24fSFrançois Tigeot #include <linux/spinlock.h> 3394a312a1SFrançois Tigeot 34b4b38be0SFrançois Tigeot #include <linux/mutex.h> 35ba55f2f5SFrançois Tigeot 36*a85cb24fSFrançois Tigeot #include <sys/refcount.h> 37*a85cb24fSFrançois Tigeot 3894a312a1SFrançois Tigeot struct kref { 3932dbd5b5SFrançois Tigeot atomic_t refcount; 4094a312a1SFrançois Tigeot }; 4194a312a1SFrançois Tigeot 4294a312a1SFrançois Tigeot static inline void 4394a312a1SFrançois Tigeot kref_init(struct kref *kref) 4494a312a1SFrançois Tigeot { 4594a312a1SFrançois Tigeot 4632dbd5b5SFrançois Tigeot refcount_init(&kref->refcount.counter, 1); 4794a312a1SFrançois Tigeot } 4894a312a1SFrançois Tigeot 49*a85cb24fSFrançois Tigeot static inline unsigned int 50*a85cb24fSFrançois Tigeot kref_read(const struct kref *kref) 51*a85cb24fSFrançois Tigeot { 52*a85cb24fSFrançois Tigeot return atomic_read(&kref->refcount); 53*a85cb24fSFrançois Tigeot } 54*a85cb24fSFrançois Tigeot 5594a312a1SFrançois Tigeot static inline void 5694a312a1SFrançois Tigeot kref_get(struct kref *kref) 5794a312a1SFrançois Tigeot { 5894a312a1SFrançois Tigeot 5932dbd5b5SFrançois Tigeot refcount_acquire(&kref->refcount.counter); 6094a312a1SFrançois Tigeot } 6194a312a1SFrançois Tigeot 6294a312a1SFrançois Tigeot static inline int 6394a312a1SFrançois Tigeot kref_put(struct kref *kref, void (*rel)(struct kref *kref)) 6494a312a1SFrançois Tigeot { 6594a312a1SFrançois Tigeot 6632dbd5b5SFrançois Tigeot if (refcount_release(&kref->refcount.counter)) { 6732dbd5b5SFrançois Tigeot rel(kref); 6832dbd5b5SFrançois Tigeot return 1; 6932dbd5b5SFrançois Tigeot } 7032dbd5b5SFrançois Tigeot return 0; 7132dbd5b5SFrançois Tigeot } 7232dbd5b5SFrançois Tigeot 7332dbd5b5SFrançois Tigeot static inline int 7432dbd5b5SFrançois Tigeot kref_sub(struct kref *kref, unsigned int count, 7532dbd5b5SFrançois Tigeot void (*rel)(struct kref *kref)) 7632dbd5b5SFrançois Tigeot { 7732dbd5b5SFrançois Tigeot if (refcount_release_n(&kref->refcount.counter, count)) { 7894a312a1SFrançois Tigeot rel(kref); 7994a312a1SFrançois Tigeot return 1; 8094a312a1SFrançois Tigeot } 8194a312a1SFrançois Tigeot return 0; 8294a312a1SFrançois Tigeot } 8394a312a1SFrançois Tigeot 841dca5014SFrançois Tigeot /* 851dca5014SFrançois Tigeot * kref_get_unless_zero: Increment refcount for object unless it is zero. 861dca5014SFrançois Tigeot */ 871dca5014SFrançois Tigeot static inline int __must_check kref_get_unless_zero(struct kref *kref) 881dca5014SFrançois Tigeot { 891dca5014SFrançois Tigeot return atomic_add_unless(&kref->refcount, 1, 0); 901dca5014SFrançois Tigeot } 911dca5014SFrançois Tigeot 92b4b38be0SFrançois Tigeot static inline int kref_put_mutex(struct kref *kref, 93b4b38be0SFrançois Tigeot void (*release)(struct kref *kref), 94b4b38be0SFrançois Tigeot struct lock *lock) 95b4b38be0SFrançois Tigeot { 96b4b38be0SFrançois Tigeot if (!atomic_add_unless(&kref->refcount, -1, 1)) { 97b4b38be0SFrançois Tigeot mutex_lock(lock); 98b4b38be0SFrançois Tigeot if (likely(atomic_dec_and_test(&kref->refcount))) { 99b4b38be0SFrançois Tigeot release(kref); 100b4b38be0SFrançois Tigeot return 1; 101b4b38be0SFrançois Tigeot } 102b4b38be0SFrançois Tigeot mutex_unlock(lock); 103b4b38be0SFrançois Tigeot return 0; 104b4b38be0SFrançois Tigeot } 105b4b38be0SFrançois Tigeot 106b4b38be0SFrançois Tigeot return 0; 107b4b38be0SFrançois Tigeot } 108b4b38be0SFrançois Tigeot 1091dca5014SFrançois Tigeot #endif /* _LINUX_KREF_H_ */ 110