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. 532dbd5b5SFrançois Tigeot * Copyright (c) 2013 François Tigeot 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 3294a312a1SFrançois Tigeot #include <sys/refcount.h> 3394a312a1SFrançois Tigeot 34ba55f2f5SFrançois Tigeot #include <linux/atomic.h> 35*b4b38be0SFrançois Tigeot #include <linux/mutex.h> 36ba55f2f5SFrançois Tigeot 3794a312a1SFrançois Tigeot struct kref { 3832dbd5b5SFrançois Tigeot atomic_t refcount; 3994a312a1SFrançois Tigeot }; 4094a312a1SFrançois Tigeot 4194a312a1SFrançois Tigeot static inline void 4294a312a1SFrançois Tigeot kref_init(struct kref *kref) 4394a312a1SFrançois Tigeot { 4494a312a1SFrançois Tigeot 4532dbd5b5SFrançois Tigeot refcount_init(&kref->refcount.counter, 1); 4694a312a1SFrançois Tigeot } 4794a312a1SFrançois Tigeot 4894a312a1SFrançois Tigeot static inline void 4994a312a1SFrançois Tigeot kref_get(struct kref *kref) 5094a312a1SFrançois Tigeot { 5194a312a1SFrançois Tigeot 5232dbd5b5SFrançois Tigeot refcount_acquire(&kref->refcount.counter); 5394a312a1SFrançois Tigeot } 5494a312a1SFrançois Tigeot 5594a312a1SFrançois Tigeot static inline int 5694a312a1SFrançois Tigeot kref_put(struct kref *kref, void (*rel)(struct kref *kref)) 5794a312a1SFrançois Tigeot { 5894a312a1SFrançois Tigeot 5932dbd5b5SFrançois Tigeot if (refcount_release(&kref->refcount.counter)) { 6032dbd5b5SFrançois Tigeot rel(kref); 6132dbd5b5SFrançois Tigeot return 1; 6232dbd5b5SFrançois Tigeot } 6332dbd5b5SFrançois Tigeot return 0; 6432dbd5b5SFrançois Tigeot } 6532dbd5b5SFrançois Tigeot 6632dbd5b5SFrançois Tigeot static inline int 6732dbd5b5SFrançois Tigeot kref_sub(struct kref *kref, unsigned int count, 6832dbd5b5SFrançois Tigeot void (*rel)(struct kref *kref)) 6932dbd5b5SFrançois Tigeot { 7032dbd5b5SFrançois Tigeot if (refcount_release_n(&kref->refcount.counter, count)) { 7194a312a1SFrançois Tigeot rel(kref); 7294a312a1SFrançois Tigeot return 1; 7394a312a1SFrançois Tigeot } 7494a312a1SFrançois Tigeot return 0; 7594a312a1SFrançois Tigeot } 7694a312a1SFrançois Tigeot 771dca5014SFrançois Tigeot /* 781dca5014SFrançois Tigeot * kref_get_unless_zero: Increment refcount for object unless it is zero. 791dca5014SFrançois Tigeot */ 801dca5014SFrançois Tigeot static inline int __must_check kref_get_unless_zero(struct kref *kref) 811dca5014SFrançois Tigeot { 821dca5014SFrançois Tigeot return atomic_add_unless(&kref->refcount, 1, 0); 831dca5014SFrançois Tigeot } 841dca5014SFrançois Tigeot 85*b4b38be0SFrançois Tigeot static inline int kref_put_mutex(struct kref *kref, 86*b4b38be0SFrançois Tigeot void (*release)(struct kref *kref), 87*b4b38be0SFrançois Tigeot struct lock *lock) 88*b4b38be0SFrançois Tigeot { 89*b4b38be0SFrançois Tigeot if (!atomic_add_unless(&kref->refcount, -1, 1)) { 90*b4b38be0SFrançois Tigeot mutex_lock(lock); 91*b4b38be0SFrançois Tigeot if (likely(atomic_dec_and_test(&kref->refcount))) { 92*b4b38be0SFrançois Tigeot release(kref); 93*b4b38be0SFrançois Tigeot return 1; 94*b4b38be0SFrançois Tigeot } 95*b4b38be0SFrançois Tigeot mutex_unlock(lock); 96*b4b38be0SFrançois Tigeot return 0; 97*b4b38be0SFrançois Tigeot } 98*b4b38be0SFrançois Tigeot 99*b4b38be0SFrançois Tigeot return 0; 100*b4b38be0SFrançois Tigeot } 101*b4b38be0SFrançois Tigeot 1021dca5014SFrançois Tigeot #endif /* _LINUX_KREF_H_ */ 103