// SPDX-License-Identifier: GPL-2.0-or-later /* FS-Cache cache handling * * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com)
*/
/** * fscache_acquire_cache - Acquire a cache-level cookie. * @name: The name of the cache. * * Get a cookie to represent an actual cache. If a name is given and there is * a nameless cache record available, this will acquire that and set its name, * directing all the volumes using it to this cache. * * The cache will be switched over to the preparing state if not currently in * use, otherwise -EBUSY will be returned.
*/ struct fscache_cache *fscache_acquire_cache(constchar *name)
{ struct fscache_cache *cache;
ASSERT(name);
cache = fscache_lookup_cache(name, true); if (IS_ERR(cache)) return cache;
if (!fscache_set_cache_state_maybe(cache,
FSCACHE_CACHE_IS_NOT_PRESENT,
FSCACHE_CACHE_IS_PREPARING)) {
pr_warn("Cache tag %s in use\n", name);
fscache_put_cache(cache, fscache_cache_put_cache); return ERR_PTR(-EBUSY);
}
/** * fscache_put_cache - Release a cache-level cookie. * @cache: The cache cookie to be released * @where: An indication of where the release happened * * Release the caller's reference on a cache-level cookie. The @where * indication should give information about the circumstances in which the call * occurs and will be logged through a tracepoint.
*/ void fscache_put_cache(struct fscache_cache *cache, enum fscache_cache_trace where)
{ unsignedint debug_id; bool zero; int ref;
if (zero) {
down_write(&fscache_addremove_sem);
list_del_init(&cache->cache_link);
up_write(&fscache_addremove_sem);
kfree(cache->name);
kfree(cache);
}
}
/** * fscache_relinquish_cache - Reset cache state and release cookie * @cache: The cache cookie to be released * * Reset the state of a cache and release the caller's reference on a cache * cookie.
*/ void fscache_relinquish_cache(struct fscache_cache *cache)
{ enum fscache_cache_trace where =
(cache->state == FSCACHE_CACHE_IS_PREPARING) ?
fscache_cache_put_prep_failed :
fscache_cache_put_relinquish;
/** * fscache_add_cache - Declare a cache as being open for business * @cache: The cache-level cookie representing the cache * @ops: Table of cache operations to use * @cache_priv: Private data for the cache record * * Add a cache to the system, making it available for netfs's to use. * * See Documentation/filesystems/caching/backend-api.rst for a complete * description.
*/ int fscache_add_cache(struct fscache_cache *cache, conststruct fscache_cache_ops *ops, void *cache_priv)
{ int n_accesses;
/* Get a ref on the cache cookie and keep its n_accesses counter raised * by 1 to prevent wakeups from transitioning it to 0 until we're * withdrawing caching services from it.
*/
n_accesses = atomic_inc_return(&cache->n_accesses);
trace_fscache_access_cache(cache->debug_id, refcount_read(&cache->ref),
n_accesses, fscache_access_cache_pin);
/** * fscache_begin_cache_access - Pin a cache so it can be accessed * @cache: The cache-level cookie * @why: An indication of the circumstances of the access for tracing * * Attempt to pin the cache to prevent it from going away whilst we're * accessing it and returns true if successful. This works as follows: * * (1) If the cache tests as not live (state is not FSCACHE_CACHE_IS_ACTIVE), * then we return false to indicate access was not permitted. * * (2) If the cache tests as live, then we increment the n_accesses count and * then recheck the liveness, ending the access if it ceased to be live. * * (3) When we end the access, we decrement n_accesses and wake up the any * waiters if it reaches 0. * * (4) Whilst the cache is caching, n_accesses is kept artificially * incremented to prevent wakeups from happening. * * (5) When the cache is taken offline, the state is changed to prevent new * accesses, n_accesses is decremented and we wait for n_accesses to * become 0.
*/ bool fscache_begin_cache_access(struct fscache_cache *cache, enum fscache_access_trace why)
{ int n_accesses;
if (!fscache_cache_is_live(cache)) returnfalse;
n_accesses = atomic_inc_return(&cache->n_accesses);
smp_mb__after_atomic(); /* Reread live flag after n_accesses */
trace_fscache_access_cache(cache->debug_id, refcount_read(&cache->ref),
n_accesses, why); if (!fscache_cache_is_live(cache)) {
fscache_end_cache_access(cache, fscache_access_unlive); returnfalse;
} returntrue;
}
/** * fscache_end_cache_access - Unpin a cache at the end of an access. * @cache: The cache-level cookie * @why: An indication of the circumstances of the access for tracing * * Unpin a cache after we've accessed it. The @why indicator is merely * provided for tracing purposes.
*/ void fscache_end_cache_access(struct fscache_cache *cache, enum fscache_access_trace why)
{ int n_accesses;
/** * fscache_io_error - Note a cache I/O error * @cache: The record describing the cache * * Note that an I/O error occurred in a cache and that it should no longer be * used for anything. This also reports the error into the kernel log. * * See Documentation/filesystems/caching/backend-api.rst for a complete * description.
*/ void fscache_io_error(struct fscache_cache *cache)
{ if (fscache_set_cache_state_maybe(cache,
FSCACHE_CACHE_IS_ACTIVE,
FSCACHE_CACHE_GOT_IOERROR))
pr_err("Cache '%s' stopped due to I/O error\n",
cache->name);
}
EXPORT_SYMBOL(fscache_io_error);
/** * fscache_withdraw_cache - Withdraw a cache from the active service * @cache: The cache cookie * * Begin the process of withdrawing a cache from service. This stops new * cache-level and volume-level accesses from taking place and waits for * currently ongoing cache-level accesses to end.
*/ void fscache_withdraw_cache(struct fscache_cache *cache)
{ int n_accesses;
/* * Generate a list of caches in /proc/fs/fscache/caches
*/ staticint fscache_caches_seq_show(struct seq_file *m, void *v)
{ struct fscache_cache *cache;
if (v == &fscache_caches) {
seq_puts(m, "CACHE REF VOLS OBJS ACCES S NAME\n" "======== ===== ===== ===== ===== = ===============\n"
); return 0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.