time_t last_refresh; /* If CACHE_PENDING, this is when upcall
* was sent, else this is when update was received
*/
- atomic_t refcnt;
+ struct kref ref;
unsigned long flags;
};
#define CACHE_VALID 0 /* Entry contains valid data */
atomic_t inuse; /* active user-space update or lookup */
char *name;
- void (*cache_put)(struct cache_head *,
- struct cache_detail*);
+ void (*cache_put)(struct kref *);
void (*cache_request)(struct cache_detail *cd,
struct cache_head *h,
static inline struct cache_head *cache_get(struct cache_head *h)
{
- atomic_inc(&h->refcnt);
+ kref_get(&h->ref);
return h;
}
-static inline int cache_put(struct cache_head *h, struct cache_detail *cd)
+static inline void cache_put(struct cache_head *h, struct cache_detail *cd)
{
- if (atomic_read(&h->refcnt) <= 2 &&
+ if (atomic_read(&h->ref.refcount) <= 2 &&
h->expiry_time < cd->nextcheck)
cd->nextcheck = h->expiry_time;
- return atomic_dec_and_test(&h->refcnt);
+ kref_put(&h->ref, cd->cache_put);
+}
+
+static inline int cache_valid(struct cache_head *h)
+{
+ /* If an item has been unhashed pending removal when
+ * the refcount drops to 0, the expiry_time will be
+ * set to 0. We don't want to consider such items
+ * valid in this context even though CACHE_VALID is
+ * set.
+ */
+ return (h->expiry_time != 0 && test_bit(CACHE_VALID, &h->flags));
}
-extern void cache_init(struct cache_head *h);
-extern void cache_fresh(struct cache_detail *detail,
- struct cache_head *head, time_t expiry);
extern int cache_check(struct cache_detail *detail,
struct cache_head *h, struct cache_req *rqstp);
extern void cache_flush(void);