1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* FS-Cache cache handling
4 * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
8 #define FSCACHE_DEBUG_LEVEL CACHE
9 #include <linux/export.h>
10 #include <linux/slab.h>
13 static LIST_HEAD(fscache_caches
);
14 DECLARE_RWSEM(fscache_addremove_sem
);
15 EXPORT_SYMBOL(fscache_addremove_sem
);
16 DECLARE_WAIT_QUEUE_HEAD(fscache_clearance_waiters
);
17 EXPORT_SYMBOL(fscache_clearance_waiters
);
19 static atomic_t fscache_cache_debug_id
;
22 * Allocate a cache cookie.
24 static struct fscache_cache
*fscache_alloc_cache(const char *name
)
26 struct fscache_cache
*cache
;
28 cache
= kzalloc(sizeof(*cache
), GFP_KERNEL
);
31 cache
->name
= kstrdup(name
, GFP_KERNEL
);
37 refcount_set(&cache
->ref
, 1);
38 INIT_LIST_HEAD(&cache
->cache_link
);
39 cache
->debug_id
= atomic_inc_return(&fscache_cache_debug_id
);
44 static bool fscache_get_cache_maybe(struct fscache_cache
*cache
,
45 enum fscache_cache_trace where
)
50 success
= __refcount_inc_not_zero(&cache
->ref
, &ref
);
52 trace_fscache_cache(cache
->debug_id
, ref
+ 1, where
);
57 * Look up a cache cookie.
59 struct fscache_cache
*fscache_lookup_cache(const char *name
, bool is_cache
)
61 struct fscache_cache
*candidate
, *cache
, *unnamed
= NULL
;
63 /* firstly check for the existence of the cache under read lock */
64 down_read(&fscache_addremove_sem
);
66 list_for_each_entry(cache
, &fscache_caches
, cache_link
) {
67 if (cache
->name
&& name
&& strcmp(cache
->name
, name
) == 0 &&
68 fscache_get_cache_maybe(cache
, fscache_cache_get_acquire
))
70 if (!cache
->name
&& !name
&&
71 fscache_get_cache_maybe(cache
, fscache_cache_get_acquire
))
76 list_for_each_entry(cache
, &fscache_caches
, cache_link
) {
78 fscache_get_cache_maybe(cache
, fscache_cache_get_acquire
))
83 up_read(&fscache_addremove_sem
);
85 /* the cache does not exist - create a candidate */
86 candidate
= fscache_alloc_cache(name
);
88 return ERR_PTR(-ENOMEM
);
90 /* write lock, search again and add if still not present */
91 down_write(&fscache_addremove_sem
);
93 list_for_each_entry(cache
, &fscache_caches
, cache_link
) {
94 if (cache
->name
&& name
&& strcmp(cache
->name
, name
) == 0 &&
95 fscache_get_cache_maybe(cache
, fscache_cache_get_acquire
))
100 fscache_get_cache_maybe(cache
, fscache_cache_get_acquire
))
105 if (unnamed
&& is_cache
&&
106 fscache_get_cache_maybe(unnamed
, fscache_cache_get_acquire
))
107 goto use_unnamed_cache
;
110 list_for_each_entry(cache
, &fscache_caches
, cache_link
) {
112 fscache_get_cache_maybe(cache
, fscache_cache_get_acquire
))
117 list_add_tail(&candidate
->cache_link
, &fscache_caches
);
118 trace_fscache_cache(candidate
->debug_id
,
119 refcount_read(&candidate
->ref
),
120 fscache_cache_new_acquire
);
121 up_write(&fscache_addremove_sem
);
125 up_read(&fscache_addremove_sem
);
129 cache
->name
= candidate
->name
;
130 candidate
->name
= NULL
;
132 up_write(&fscache_addremove_sem
);
133 kfree(candidate
->name
);
139 * fscache_acquire_cache - Acquire a cache-level cookie.
140 * @name: The name of the cache.
142 * Get a cookie to represent an actual cache. If a name is given and there is
143 * a nameless cache record available, this will acquire that and set its name,
144 * directing all the volumes using it to this cache.
146 * The cache will be switched over to the preparing state if not currently in
147 * use, otherwise -EBUSY will be returned.
149 struct fscache_cache
*fscache_acquire_cache(const char *name
)
151 struct fscache_cache
*cache
;
154 cache
= fscache_lookup_cache(name
, true);
158 if (!fscache_set_cache_state_maybe(cache
,
159 FSCACHE_CACHE_IS_NOT_PRESENT
,
160 FSCACHE_CACHE_IS_PREPARING
)) {
161 pr_warn("Cache tag %s in use\n", name
);
162 fscache_put_cache(cache
, fscache_cache_put_cache
);
163 return ERR_PTR(-EBUSY
);
168 EXPORT_SYMBOL(fscache_acquire_cache
);
171 * fscache_put_cache - Release a cache-level cookie.
172 * @cache: The cache cookie to be released
173 * @where: An indication of where the release happened
175 * Release the caller's reference on a cache-level cookie. The @where
176 * indication should give information about the circumstances in which the call
177 * occurs and will be logged through a tracepoint.
179 void fscache_put_cache(struct fscache_cache
*cache
,
180 enum fscache_cache_trace where
)
182 unsigned int debug_id
;
186 if (IS_ERR_OR_NULL(cache
))
189 debug_id
= cache
->debug_id
;
190 zero
= __refcount_dec_and_test(&cache
->ref
, &ref
);
191 trace_fscache_cache(debug_id
, ref
- 1, where
);
194 down_write(&fscache_addremove_sem
);
195 list_del_init(&cache
->cache_link
);
196 up_write(&fscache_addremove_sem
);
203 * fscache_relinquish_cache - Reset cache state and release cookie
204 * @cache: The cache cookie to be released
206 * Reset the state of a cache and release the caller's reference on a cache
209 void fscache_relinquish_cache(struct fscache_cache
*cache
)
211 enum fscache_cache_trace where
=
212 (cache
->state
== FSCACHE_CACHE_IS_PREPARING
) ?
213 fscache_cache_put_prep_failed
:
214 fscache_cache_put_relinquish
;
217 cache
->cache_priv
= NULL
;
218 fscache_set_cache_state(cache
, FSCACHE_CACHE_IS_NOT_PRESENT
);
219 fscache_put_cache(cache
, where
);
221 EXPORT_SYMBOL(fscache_relinquish_cache
);
224 * fscache_add_cache - Declare a cache as being open for business
225 * @cache: The cache-level cookie representing the cache
226 * @ops: Table of cache operations to use
227 * @cache_priv: Private data for the cache record
229 * Add a cache to the system, making it available for netfs's to use.
231 * See Documentation/filesystems/caching/backend-api.rst for a complete
234 int fscache_add_cache(struct fscache_cache
*cache
,
235 const struct fscache_cache_ops
*ops
,
240 _enter("{%s,%s}", ops
->name
, cache
->name
);
242 BUG_ON(fscache_cache_state(cache
) != FSCACHE_CACHE_IS_PREPARING
);
244 /* Get a ref on the cache cookie and keep its n_accesses counter raised
245 * by 1 to prevent wakeups from transitioning it to 0 until we're
246 * withdrawing caching services from it.
248 n_accesses
= atomic_inc_return(&cache
->n_accesses
);
249 trace_fscache_access_cache(cache
->debug_id
, refcount_read(&cache
->ref
),
250 n_accesses
, fscache_access_cache_pin
);
252 down_write(&fscache_addremove_sem
);
255 cache
->cache_priv
= cache_priv
;
256 fscache_set_cache_state(cache
, FSCACHE_CACHE_IS_ACTIVE
);
258 up_write(&fscache_addremove_sem
);
259 pr_notice("Cache \"%s\" added (type %s)\n", cache
->name
, ops
->name
);
260 _leave(" = 0 [%s]", cache
->name
);
263 EXPORT_SYMBOL(fscache_add_cache
);
266 * fscache_begin_cache_access - Pin a cache so it can be accessed
267 * @cache: The cache-level cookie
268 * @why: An indication of the circumstances of the access for tracing
270 * Attempt to pin the cache to prevent it from going away whilst we're
271 * accessing it and returns true if successful. This works as follows:
273 * (1) If the cache tests as not live (state is not FSCACHE_CACHE_IS_ACTIVE),
274 * then we return false to indicate access was not permitted.
276 * (2) If the cache tests as live, then we increment the n_accesses count and
277 * then recheck the liveness, ending the access if it ceased to be live.
279 * (3) When we end the access, we decrement n_accesses and wake up the any
280 * waiters if it reaches 0.
282 * (4) Whilst the cache is caching, n_accesses is kept artificially
283 * incremented to prevent wakeups from happening.
285 * (5) When the cache is taken offline, the state is changed to prevent new
286 * accesses, n_accesses is decremented and we wait for n_accesses to
289 bool fscache_begin_cache_access(struct fscache_cache
*cache
, enum fscache_access_trace why
)
293 if (!fscache_cache_is_live(cache
))
296 n_accesses
= atomic_inc_return(&cache
->n_accesses
);
297 smp_mb__after_atomic(); /* Reread live flag after n_accesses */
298 trace_fscache_access_cache(cache
->debug_id
, refcount_read(&cache
->ref
),
300 if (!fscache_cache_is_live(cache
)) {
301 fscache_end_cache_access(cache
, fscache_access_unlive
);
308 * fscache_end_cache_access - Unpin a cache at the end of an access.
309 * @cache: The cache-level cookie
310 * @why: An indication of the circumstances of the access for tracing
312 * Unpin a cache after we've accessed it. The @why indicator is merely
313 * provided for tracing purposes.
315 void fscache_end_cache_access(struct fscache_cache
*cache
, enum fscache_access_trace why
)
319 smp_mb__before_atomic();
320 n_accesses
= atomic_dec_return(&cache
->n_accesses
);
321 trace_fscache_access_cache(cache
->debug_id
, refcount_read(&cache
->ref
),
324 wake_up_var(&cache
->n_accesses
);
328 * fscache_io_error - Note a cache I/O error
329 * @cache: The record describing the cache
331 * Note that an I/O error occurred in a cache and that it should no longer be
332 * used for anything. This also reports the error into the kernel log.
334 * See Documentation/filesystems/caching/backend-api.rst for a complete
337 void fscache_io_error(struct fscache_cache
*cache
)
339 if (fscache_set_cache_state_maybe(cache
,
340 FSCACHE_CACHE_IS_ACTIVE
,
341 FSCACHE_CACHE_GOT_IOERROR
))
342 pr_err("Cache '%s' stopped due to I/O error\n",
345 EXPORT_SYMBOL(fscache_io_error
);
348 * fscache_withdraw_cache - Withdraw a cache from the active service
349 * @cache: The cache cookie
351 * Begin the process of withdrawing a cache from service. This stops new
352 * cache-level and volume-level accesses from taking place and waits for
353 * currently ongoing cache-level accesses to end.
355 void fscache_withdraw_cache(struct fscache_cache
*cache
)
359 pr_notice("Withdrawing cache \"%s\" (%u objs)\n",
360 cache
->name
, atomic_read(&cache
->object_count
));
362 fscache_set_cache_state(cache
, FSCACHE_CACHE_IS_WITHDRAWN
);
364 /* Allow wakeups on dec-to-0 */
365 n_accesses
= atomic_dec_return(&cache
->n_accesses
);
366 trace_fscache_access_cache(cache
->debug_id
, refcount_read(&cache
->ref
),
367 n_accesses
, fscache_access_cache_unpin
);
369 wait_var_event(&cache
->n_accesses
,
370 atomic_read(&cache
->n_accesses
) == 0);
372 EXPORT_SYMBOL(fscache_withdraw_cache
);
374 #ifdef CONFIG_PROC_FS
375 static const char fscache_cache_states
[NR__FSCACHE_CACHE_STATE
] = "-PAEW";
378 * Generate a list of caches in /proc/fs/fscache/caches
380 static int fscache_caches_seq_show(struct seq_file
*m
, void *v
)
382 struct fscache_cache
*cache
;
384 if (v
== &fscache_caches
) {
386 "CACHE REF VOLS OBJS ACCES S NAME\n"
387 "======== ===== ===== ===== ===== = ===============\n"
392 cache
= list_entry(v
, struct fscache_cache
, cache_link
);
394 "%08x %5d %5d %5d %5d %c %s\n",
396 refcount_read(&cache
->ref
),
397 atomic_read(&cache
->n_volumes
),
398 atomic_read(&cache
->object_count
),
399 atomic_read(&cache
->n_accesses
),
400 fscache_cache_states
[cache
->state
],
405 static void *fscache_caches_seq_start(struct seq_file
*m
, loff_t
*_pos
)
406 __acquires(fscache_addremove_sem
)
408 down_read(&fscache_addremove_sem
);
409 return seq_list_start_head(&fscache_caches
, *_pos
);
412 static void *fscache_caches_seq_next(struct seq_file
*m
, void *v
, loff_t
*_pos
)
414 return seq_list_next(v
, &fscache_caches
, _pos
);
417 static void fscache_caches_seq_stop(struct seq_file
*m
, void *v
)
418 __releases(fscache_addremove_sem
)
420 up_read(&fscache_addremove_sem
);
423 const struct seq_operations fscache_caches_seq_ops
= {
424 .start
= fscache_caches_seq_start
,
425 .next
= fscache_caches_seq_next
,
426 .stop
= fscache_caches_seq_stop
,
427 .show
= fscache_caches_seq_show
,
429 #endif /* CONFIG_PROC_FS */