2020-04-28 00:16:58 +03:00
|
|
|
.. SPDX-License-Identifier: GPL-2.0
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
=================
|
|
|
|
Cache Backend API
|
|
|
|
=================
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
The FS-Cache system provides an API by which actual caches can be supplied to
|
|
|
|
FS-Cache for it to then serve out to network filesystems and other interested
|
2021-11-10 16:25:03 +03:00
|
|
|
parties. This API is used by::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
#include <linux/fscache-cache.h>.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Overview
|
2009-04-03 19:42:36 +04:00
|
|
|
========
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Interaction with the API is handled on three levels: cache, volume and data
|
|
|
|
storage, and each level has its own type of cookie object:
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
======================= =======================
|
|
|
|
COOKIE C TYPE
|
|
|
|
======================= =======================
|
|
|
|
Cache cookie struct fscache_cache
|
|
|
|
Volume cookie struct fscache_volume
|
|
|
|
Data storage cookie struct fscache_cookie
|
|
|
|
======================= =======================
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Cookies are used to provide some filesystem data to the cache, manage state and
|
|
|
|
pin the cache during access in addition to acting as reference points for the
|
|
|
|
API functions. Each cookie has a debugging ID that is included in trace points
|
|
|
|
to make it easier to correlate traces. Note, though, that debugging IDs are
|
|
|
|
simply allocated from incrementing counters and will eventually wrap.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
The cache backend and the network filesystem can both ask for cache cookies -
|
|
|
|
and if they ask for one of the same name, they'll get the same cookie. Volume
|
|
|
|
and data cookies, however, are created at the behest of the filesystem only.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Cache Cookies
|
|
|
|
=============
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Caches are represented in the API by cache cookies. These are objects of
|
|
|
|
type::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
struct fscache_cache {
|
|
|
|
void *cache_priv;
|
|
|
|
unsigned int debug_id;
|
|
|
|
char *name;
|
2009-04-03 19:42:36 +04:00
|
|
|
...
|
|
|
|
};
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
There are a few fields that the cache backend might be interested in. The
|
|
|
|
``debug_id`` can be used in tracing to match lines referring to the same cache
|
|
|
|
and ``name`` is the name the cache was registered with. The ``cache_priv``
|
|
|
|
member is private data provided by the cache when it is brought online. The
|
|
|
|
other fields are for internal use.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Registering a Cache
|
|
|
|
===================
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
When a cache backend wants to bring a cache online, it should first register
|
|
|
|
the cache name and that will get it a cache cookie. This is done with::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
struct fscache_cache *fscache_acquire_cache(const char *name);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
This will look up and potentially create a cache cookie. The cache cookie may
|
|
|
|
have already been created by a network filesystem looking for it, in which case
|
|
|
|
that cache cookie will be used. If the cache cookie is not in use by another
|
|
|
|
cache, it will be moved into the preparing state, otherwise it will return
|
|
|
|
busy.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
If successful, the cache backend can then start setting up the cache. In the
|
|
|
|
event that the initialisation fails, the cache backend should call::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2022-04-07 13:28:32 +03:00
|
|
|
void fscache_relinquish_cache(struct fscache_cache *cache);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
to reset and discard the cookie.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Bringing a Cache Online
|
|
|
|
=======================
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Once the cache is set up, it can be brought online by calling::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
int fscache_add_cache(struct fscache_cache *cache,
|
|
|
|
const struct fscache_cache_ops *ops,
|
|
|
|
void *cache_priv);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
This stores the cache operations table pointer and cache private data into the
|
|
|
|
cache cookie and moves the cache to the active state, thereby allowing accesses
|
|
|
|
to take place.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Withdrawing a Cache From Service
|
|
|
|
================================
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
The cache backend can withdraw a cache from service by calling this function::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void fscache_withdraw_cache(struct fscache_cache *cache);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
This moves the cache to the withdrawn state to prevent new cache- and
|
|
|
|
volume-level accesses from starting and then waits for outstanding cache-level
|
|
|
|
accesses to complete.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
The cache must then go through the data storage objects it has and tell fscache
|
|
|
|
to withdraw them, calling::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void fscache_withdraw_cookie(struct fscache_cookie *cookie);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
on the cookie that each object belongs to. This schedules the specified cookie
|
|
|
|
for withdrawal. This gets offloaded to a workqueue. The cache backend can
|
2022-04-07 14:02:39 +03:00
|
|
|
wait for completion by calling::
|
2020-04-28 00:16:58 +03:00
|
|
|
|
2022-04-07 14:02:39 +03:00
|
|
|
void fscache_wait_for_objects(struct fscache_cache *cache);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Once all the cookies are withdrawn, a cache backend can withdraw all the
|
|
|
|
volumes, calling::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void fscache_withdraw_volume(struct fscache_volume *volume);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
to tell fscache that a volume has been withdrawn. This waits for all
|
|
|
|
outstanding accesses on the volume to complete before returning.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
When the the cache is completely withdrawn, fscache should be notified by
|
|
|
|
calling::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2022-04-07 13:28:32 +03:00
|
|
|
void fscache_relinquish_cache(struct fscache_cache *cache);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
to clear fields in the cookie and discard the caller's ref on it.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Volume Cookies
|
|
|
|
==============
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Within a cache, the data storage objects are organised into logical volumes.
|
|
|
|
These are represented in the API as objects of type::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
struct fscache_volume {
|
|
|
|
struct fscache_cache *cache;
|
|
|
|
void *cache_priv;
|
|
|
|
unsigned int debug_id;
|
|
|
|
char *key;
|
|
|
|
unsigned int key_hash;
|
|
|
|
...
|
|
|
|
u8 coherency_len;
|
|
|
|
u8 coherency[];
|
|
|
|
};
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
There are a number of fields here that are of interest to the caching backend:
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``cache`` - The parent cache cookie.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``cache_priv`` - A place for the cache to stash private data.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``debug_id`` - A debugging ID for logging in tracepoints.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``key`` - A printable string with no '/' characters in it that represents
|
|
|
|
the index key for the volume. The key is NUL-terminated and padded out to
|
|
|
|
a multiple of 4 bytes.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``key_hash`` - A hash of the index key. This should work out the same, no
|
|
|
|
matter the cpu arch and endianness.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``coherency`` - A piece of coherency data that should be checked when the
|
|
|
|
volume is bound to in the cache.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``coherency_len`` - The amount of data in the coherency buffer.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Data Storage Cookies
|
|
|
|
====================
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
A volume is a logical group of data storage objects, each of which is
|
|
|
|
represented to the network filesystem by a cookie. Cookies are represented in
|
|
|
|
the API as objects of type::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
struct fscache_cookie {
|
|
|
|
struct fscache_volume *volume;
|
|
|
|
void *cache_priv;
|
|
|
|
unsigned long flags;
|
|
|
|
unsigned int debug_id;
|
|
|
|
unsigned int inval_counter;
|
|
|
|
loff_t object_size;
|
|
|
|
u8 advice;
|
|
|
|
u32 key_hash;
|
|
|
|
u8 key_len;
|
|
|
|
u8 aux_len;
|
|
|
|
...
|
|
|
|
};
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
The fields in the cookie that are of interest to the cache backend are:
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``volume`` - The parent volume cookie.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``cache_priv`` - A place for the cache to stash private data.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``flags`` - A collection of bit flags, including:
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* FSCACHE_COOKIE_NO_DATA_TO_READ - There is no data available in the
|
|
|
|
cache to be read as the cookie has been created or invalidated.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* FSCACHE_COOKIE_NEEDS_UPDATE - The coherency data and/or object size has
|
|
|
|
been changed and needs committing.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* FSCACHE_COOKIE_LOCAL_WRITE - The netfs's data has been modified
|
|
|
|
locally, so the cache object may be in an incoherent state with respect
|
|
|
|
to the server.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* FSCACHE_COOKIE_HAVE_DATA - The backend should set this if it
|
|
|
|
successfully stores data into the cache.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* FSCACHE_COOKIE_RETIRED - The cookie was invalidated when it was
|
|
|
|
relinquished and the cached data should be discarded.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``debug_id`` - A debugging ID for logging in tracepoints.
|
2013-08-22 01:29:38 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``inval_counter`` - The number of invalidations done on the cookie.
|
2013-08-22 01:29:38 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``advice`` - Information about how the cookie is to be used.
|
2013-08-22 01:29:38 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``key_hash`` - A hash of the index key. This should work out the same, no
|
|
|
|
matter the cpu arch and endianness.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``key_len`` - The length of the index key.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``aux_len`` - The length of the coherency data buffer.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Each cookie has an index key, which may be stored inline to the cookie or
|
|
|
|
elsewhere. A pointer to this can be obtained by calling::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void *fscache_get_key(struct fscache_cookie *cookie);
|
2012-12-21 01:52:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
The index key is a binary blob, the storage for which is padded out to a
|
|
|
|
multiple of 4 bytes.
|
2012-12-21 01:52:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Each cookie also has a buffer for coherency data. This may also be inline or
|
|
|
|
detached from the cookie and a pointer is obtained by calling::
|
2012-12-21 01:52:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void *fscache_get_aux(struct fscache_cookie *cookie);
|
2012-12-21 01:52:36 +04:00
|
|
|
|
|
|
|
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Cookie Accounting
|
|
|
|
=================
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Data storage cookies are counted and this is used to block cache withdrawal
|
|
|
|
completion until all objects have been destroyed. The following functions are
|
|
|
|
provided to the cache to deal with that::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void fscache_count_object(struct fscache_cache *cache);
|
|
|
|
void fscache_uncount_object(struct fscache_cache *cache);
|
|
|
|
void fscache_wait_for_objects(struct fscache_cache *cache);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
The count function records the allocation of an object in a cache and the
|
|
|
|
uncount function records its destruction. Warning: by the time the uncount
|
|
|
|
function returns, the cache may have been destroyed.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
The wait function can be used during the withdrawal procedure to wait for
|
|
|
|
fscache to finish withdrawing all the objects in the cache. When it completes,
|
|
|
|
there will be no remaining objects referring to the cache object or any volume
|
|
|
|
objects.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Cache Management API
|
|
|
|
====================
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
The cache backend implements the cache management API by providing a table of
|
|
|
|
operations that fscache can use to manage various aspects of the cache. These
|
|
|
|
are held in a structure of type::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
struct fscache_cache_ops {
|
|
|
|
const char *name;
|
|
|
|
...
|
|
|
|
};
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
This contains a printable name for the cache backend driver plus a number of
|
|
|
|
pointers to methods to allow fscache to request management of the cache:
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* Set up a volume cookie [optional]::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void (*acquire_volume)(struct fscache_volume *volume);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
This method is called when a volume cookie is being created. The caller
|
|
|
|
holds a cache-level access pin to prevent the cache from going away for
|
|
|
|
the duration. This method should set up the resources to access a volume
|
|
|
|
in the cache and should not return until it has done so.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
If successful, it can set ``cache_priv`` to its own data.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* Clean up volume cookie [optional]::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void (*free_volume)(struct fscache_volume *volume);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
This method is called when a volume cookie is being released if
|
|
|
|
``cache_priv`` is set.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* Look up a cookie in the cache [mandatory]::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
bool (*lookup_cookie)(struct fscache_cookie *cookie);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
This method is called to look up/create the resources needed to access the
|
|
|
|
data storage for a cookie. It is called from a worker thread with a
|
|
|
|
volume-level access pin in the cache to prevent it from being withdrawn.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
True should be returned if successful and false otherwise. If false is
|
|
|
|
returned, the withdraw_cookie op (see below) will be called.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
If lookup fails, but the object could still be created (e.g. it hasn't
|
|
|
|
been cached before), then::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void fscache_cookie_lookup_negative(
|
|
|
|
struct fscache_cookie *cookie);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
can be called to let the network filesystem proceed and start downloading
|
|
|
|
stuff whilst the cache backend gets on with the job of creating things.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
If successful, ``cookie->cache_priv`` can be set.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* Withdraw an object without any cookie access counts held [mandatory]::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void (*withdraw_cookie)(struct fscache_cookie *cookie);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
This method is called to withdraw a cookie from service. It will be
|
|
|
|
called when the cookie is relinquished by the netfs, withdrawn or culled
|
|
|
|
by the cache backend or closed after a period of non-use by fscache.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
The caller doesn't hold any access pins, but it is called from a
|
|
|
|
non-reentrant work item to manage races between the various ways
|
|
|
|
withdrawal can occur.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
The cookie will have the ``FSCACHE_COOKIE_RETIRED`` flag set on it if the
|
|
|
|
associated data is to be removed from the cache.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* Change the size of a data storage object [mandatory]::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void (*resize_cookie)(struct netfs_cache_resources *cres,
|
|
|
|
loff_t new_size);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
This method is called to inform the cache backend of a change in size of
|
|
|
|
the netfs file due to local truncation. The cache backend should make all
|
|
|
|
of the changes it needs to make before returning as this is done under the
|
|
|
|
netfs inode mutex.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
The caller holds a cookie-level access pin to prevent a race with
|
|
|
|
withdrawal and the netfs must have the cookie marked in-use to prevent
|
|
|
|
garbage collection or culling from removing any resources.
|
FS-Cache: Fix operation state management and accounting
Fix the state management of internal fscache operations and the accounting of
what operations are in what states.
This is done by:
(1) Give struct fscache_operation a enum variable that directly represents the
state it's currently in, rather than spreading this knowledge over a bunch
of flags, who's processing the operation at the moment and whether it is
queued or not.
This makes it easier to write assertions to check the state at various
points and to prevent invalid state transitions.
(2) Add an 'operation complete' state and supply a function to indicate the
completion of an operation (fscache_op_complete()) and make things call
it. The final call to fscache_put_operation() can then check that an op
in the appropriate state (complete or cancelled).
(3) Adjust the use of object->n_ops, ->n_in_progress, ->n_exclusive to better
govern the state of an object:
(a) The ->n_ops is now the number of extant operations on the object
and is now decremented by fscache_put_operation() only.
(b) The ->n_in_progress is simply the number of objects that have been
taken off of the object's pending queue for the purposes of being
run. This is decremented by fscache_op_complete() only.
(c) The ->n_exclusive is the number of exclusive ops that have been
submitted and queued or are in progress. It is decremented by
fscache_op_complete() and by fscache_cancel_op().
fscache_put_operation() and fscache_operation_gc() now no longer try to
clean up ->n_exclusive and ->n_in_progress. That was leading to double
decrements against fscache_cancel_op().
fscache_cancel_op() now no longer decrements ->n_ops. That was leading to
double decrements against fscache_put_operation().
fscache_submit_exclusive_op() now decides whether it has to queue an op
based on ->n_in_progress being > 0 rather than ->n_ops > 0 as the latter
will persist in being true even after all preceding operations have been
cancelled or completed. Furthermore, if an object is active and there are
runnable ops against it, there must be at least one op running.
(4) Add a remaining-pages counter (n_pages) to struct fscache_retrieval and
provide a function to record completion of the pages as they complete.
When n_pages reaches 0, the operation is deemed to be complete and
fscache_op_complete() is called.
Add calls to fscache_retrieval_complete() anywhere we've finished with a
page we've been given to read or allocate for. This includes places where
we just return pages to the netfs for reading from the server and where
accessing the cache fails and we discard the proposed netfs page.
The bugs in the unfixed state management manifest themselves as oopses like the
following where the operation completion gets out of sync with return of the
cookie by the netfs. This is possible because the cache unlocks and returns
all the netfs pages before recording its completion - which means that there's
nothing to stop the netfs discarding them and returning the cookie.
FS-Cache: Cookie 'NFS.fh' still has outstanding reads
------------[ cut here ]------------
kernel BUG at fs/fscache/cookie.c:519!
invalid opcode: 0000 [#1] SMP
CPU 1
Modules linked in: cachefiles nfs fscache auth_rpcgss nfs_acl lockd sunrpc
Pid: 400, comm: kswapd0 Not tainted 3.1.0-rc7-fsdevel+ #1090 /DG965RY
RIP: 0010:[<ffffffffa007050a>] [<ffffffffa007050a>] __fscache_relinquish_cookie+0x170/0x343 [fscache]
RSP: 0018:ffff8800368cfb00 EFLAGS: 00010282
RAX: 000000000000003c RBX: ffff880023cc8790 RCX: 0000000000000000
RDX: 0000000000002f2e RSI: 0000000000000001 RDI: ffffffff813ab86c
RBP: ffff8800368cfb50 R08: 0000000000000002 R09: 0000000000000000
R10: ffff88003a1b7890 R11: ffff88001df6e488 R12: ffff880023d8ed98
R13: ffff880023cc8798 R14: 0000000000000004 R15: ffff88003b8bf370
FS: 0000000000000000(0000) GS:ffff88003bd00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 00000000008ba008 CR3: 0000000023d93000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process kswapd0 (pid: 400, threadinfo ffff8800368ce000, task ffff88003b8bf040)
Stack:
ffff88003b8bf040 ffff88001df6e528 ffff88001df6e528 ffffffffa00b46b0
ffff88003b8bf040 ffff88001df6e488 ffff88001df6e620 ffffffffa00b46b0
ffff88001ebd04c8 0000000000000004 ffff8800368cfb70 ffffffffa00b2c91
Call Trace:
[<ffffffffa00b2c91>] nfs_fscache_release_inode_cookie+0x3b/0x47 [nfs]
[<ffffffffa008f25f>] nfs_clear_inode+0x3c/0x41 [nfs]
[<ffffffffa0090df1>] nfs4_evict_inode+0x2f/0x33 [nfs]
[<ffffffff810d8d47>] evict+0xa1/0x15c
[<ffffffff810d8e2e>] dispose_list+0x2c/0x38
[<ffffffff810d9ebd>] prune_icache_sb+0x28c/0x29b
[<ffffffff810c56b7>] prune_super+0xd5/0x140
[<ffffffff8109b615>] shrink_slab+0x102/0x1ab
[<ffffffff8109d690>] balance_pgdat+0x2f2/0x595
[<ffffffff8103e009>] ? process_timeout+0xb/0xb
[<ffffffff8109dba3>] kswapd+0x270/0x289
[<ffffffff8104c5ea>] ? __init_waitqueue_head+0x46/0x46
[<ffffffff8109d933>] ? balance_pgdat+0x595/0x595
[<ffffffff8104bf7a>] kthread+0x7f/0x87
[<ffffffff813ad6b4>] kernel_thread_helper+0x4/0x10
[<ffffffff81026b98>] ? finish_task_switch+0x45/0xc0
[<ffffffff813abcdd>] ? retint_restore_args+0xe/0xe
[<ffffffff8104befb>] ? __init_kthread_worker+0x53/0x53
[<ffffffff813ad6b0>] ? gs_change+0xb/0xb
Signed-off-by: David Howells <dhowells@redhat.com>
2012-12-21 01:52:35 +04:00
|
|
|
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* Invalidate a data storage object [mandatory]::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
bool (*invalidate_cookie)(struct fscache_cookie *cookie);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
This is called when the network filesystem detects a third-party
|
|
|
|
modification or when an O_DIRECT write is made locally. This requests
|
|
|
|
that the cache backend should throw away all the data in the cache for
|
|
|
|
this object and start afresh. It should return true if successful and
|
|
|
|
false otherwise.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
On entry, new I O/operations are blocked. Once the cache is in a position
|
|
|
|
to accept I/O again, the backend should release the block by calling::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void fscache_resume_after_invalidation(struct fscache_cookie *cookie);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
If the method returns false, caching will be withdrawn for this cookie.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* Prepare to make local modifications to the cache [mandatory]::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void (*prepare_to_write)(struct fscache_cookie *cookie);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
This method is called when the network filesystem finds that it is going
|
|
|
|
to need to modify the contents of the cache due to local writes or
|
|
|
|
truncations. This gives the cache a chance to note that a cache object
|
|
|
|
may be incoherent with respect to the server and may need writing back
|
|
|
|
later. This may also cause the cached data to be scrapped on later
|
|
|
|
rebinding if not properly committed.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* Begin an operation for the netfs lib [mandatory]::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
bool (*begin_operation)(struct netfs_cache_resources *cres,
|
|
|
|
enum fscache_want_state want_state);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
This method is called when an I/O operation is being set up (read, write
|
|
|
|
or resize). The caller holds an access pin on the cookie and must have
|
|
|
|
marked the cookie as in-use.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
If it can, the backend should attach any resources it needs to keep around
|
|
|
|
to the netfs_cache_resources object and return true.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
If it can't complete the setup, it should return false.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
The want_state parameter indicates the state the caller needs the cache
|
|
|
|
object to be in and what it wants to do during the operation:
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``FSCACHE_WANT_PARAMS`` - The caller just wants to access cache
|
|
|
|
object parameters; it doesn't need to do data I/O yet.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``FSCACHE_WANT_READ`` - The caller wants to read data.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* ``FSCACHE_WANT_WRITE`` - The caller wants to write to or resize the
|
|
|
|
cache object.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Note that there won't necessarily be anything attached to the cookie's
|
|
|
|
cache_priv yet if the cookie is still being created.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Data I/O API
|
|
|
|
============
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
A cache backend provides a data I/O API by through the netfs library's ``struct
|
|
|
|
netfs_cache_ops`` attached to a ``struct netfs_cache_resources`` by the
|
|
|
|
``begin_operation`` method described above.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
See the Documentation/filesystems/netfs_library.rst for a description.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Miscellaneous Functions
|
|
|
|
=======================
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
FS-Cache provides some utilities that a cache backend may make use of:
|
|
|
|
|
2020-04-28 00:16:58 +03:00
|
|
|
* Note occurrence of an I/O error in a cache::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void fscache_io_error(struct fscache_cache *cache);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
This tells FS-Cache that an I/O error occurred in the cache. This
|
|
|
|
prevents any new I/O from being started on the cache.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
This does not actually withdraw the cache. That must be done separately.
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* Note cessation of caching on a cookie due to failure::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void fscache_caching_failed(struct fscache_cookie *cookie);
|
2015-02-20 02:47:31 +03:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
This notes that a the caching that was being done on a cookie failed in
|
|
|
|
some way, for instance the backing storage failed to be created or
|
|
|
|
invalidation failed and that no further I/O operations should take place
|
|
|
|
on it until the cache is reset.
|
2020-04-28 00:16:58 +03:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* Count I/O requests::
|
2020-04-28 00:16:58 +03:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void fscache_count_read(void);
|
|
|
|
void fscache_count_write(void);
|
2020-04-28 00:16:58 +03:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
These record reads and writes from/to the cache. The numbers are
|
|
|
|
displayed in /proc/fs/fscache/stats.
|
2015-02-20 02:47:31 +03:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* Count out-of-space errors::
|
2015-02-20 02:47:31 +03:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void fscache_count_no_write_space(void);
|
|
|
|
void fscache_count_no_create_space(void);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
These record ENOSPC errors in the cache, divided into failures of data
|
|
|
|
writes and failures of filesystem object creations (e.g. mkdir).
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* Count objects culled::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
void fscache_count_culled(void);
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
This records the culling of an object.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
* Get the cookie from a set of cache resources::
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
struct fscache_cookie *fscache_cres_cookie(struct netfs_cache_resources *cres)
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
Pull a pointer to the cookie from the cache resources. This may return a
|
|
|
|
NULL cookie if no cookie was set.
|
2009-04-03 19:42:36 +04:00
|
|
|
|
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
API Function Reference
|
|
|
|
======================
|
2009-04-03 19:42:36 +04:00
|
|
|
|
2021-11-10 16:25:03 +03:00
|
|
|
.. kernel-doc:: include/linux/fscache-cache.h
|