diff options
Diffstat (limited to 'Documentation/filesystems/caching/backend-api.rst')
-rw-r--r-- | Documentation/filesystems/caching/backend-api.rst | 850 |
1 files changed, 301 insertions, 549 deletions
diff --git a/Documentation/filesystems/caching/backend-api.rst b/Documentation/filesystems/caching/backend-api.rst index 19fbf6b9aa36..be793c49a772 100644 --- a/Documentation/filesystems/caching/backend-api.rst +++ b/Documentation/filesystems/caching/backend-api.rst @@ -1,727 +1,479 @@ .. SPDX-License-Identifier: GPL-2.0 -========================== -FS-Cache Cache backend API -========================== +================= +Cache Backend API +================= 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 -parties. +parties. This API is used by:: -This API is declared in <linux/fscache-cache.h>. + #include <linux/fscache-cache.h>. -Initialising and Registering a Cache -==================================== - -To start off, a cache definition must be initialised and registered for each -cache the backend wants to make available. For instance, CacheFS does this in -the fill_super() operation on mounting. - -The cache definition (struct fscache_cache) should be initialised by calling:: - - void fscache_init_cache(struct fscache_cache *cache, - struct fscache_cache_ops *ops, - const char *idfmt, - ...); - -Where: - - * "cache" is a pointer to the cache definition; - - * "ops" is a pointer to the table of operations that the backend supports on - this cache; and - - * "idfmt" is a format and printf-style arguments for constructing a label - for the cache. - - -The cache should then be registered with FS-Cache by passing a pointer to the -previously initialised cache definition to:: - - int fscache_add_cache(struct fscache_cache *cache, - struct fscache_object *fsdef, - const char *tagname); - -Two extra arguments should also be supplied: - - * "fsdef" which should point to the object representation for the FS-Cache - master index in this cache. Netfs primary index entries will be created - here. FS-Cache keeps the caller's reference to the index object if - successful and will release it upon withdrawal of the cache. - - * "tagname" which, if given, should be a text string naming this cache. If - this is NULL, the identifier will be used instead. For CacheFS, the - identifier is set to name the underlying block device and the tag can be - supplied by mount. - -This function may return -ENOMEM if it ran out of memory or -EEXIST if the tag -is already in use. 0 will be returned on success. - - -Unregistering a Cache -===================== - -A cache can be withdrawn from the system by calling this function with a -pointer to the cache definition:: - - void fscache_withdraw_cache(struct fscache_cache *cache); - -In CacheFS's case, this is called by put_super(). - - -Security +Overview ======== -The cache methods are executed one of two contexts: - - (1) that of the userspace process that issued the netfs operation that caused - the cache method to be invoked, or - - (2) that of one of the processes in the FS-Cache thread pool. - -In either case, this may not be an appropriate context in which to access the -cache. - -The calling process's fsuid, fsgid and SELinux security identities may need to -be masqueraded for the duration of the cache driver's access to the cache. -This is left to the cache to handle; FS-Cache makes no effort in this regard. - +Interaction with the API is handled on three levels: cache, volume and data +storage, and each level has its own type of cookie object: -Control and Statistics Presentation -=================================== + ======================= ======================= + COOKIE C TYPE + ======================= ======================= + Cache cookie struct fscache_cache + Volume cookie struct fscache_volume + Data storage cookie struct fscache_cookie + ======================= ======================= -The cache may present data to the outside world through FS-Cache's interfaces -in sysfs and procfs - the former for control and the latter for statistics. +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. -A sysfs directory called /sys/fs/fscache/<cachetag>/ is created if CONFIG_SYSFS -is enabled. This is accessible through the kobject struct fscache_cache::kobj -and is for use by the cache as it sees fit. +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. -Relevant Data Structures -======================== +Cache Cookies +============= - * Index/Data file FS-Cache representation cookie:: +Caches are represented in the API by cache cookies. These are objects of +type:: - struct fscache_cookie { - struct fscache_object_def *def; - struct fscache_netfs *netfs; - void *netfs_data; - ... - }; - - The fields that might be of use to the backend describe the object - definition, the netfs definition and the netfs's data for this cookie. - The object definition contain functions supplied by the netfs for loading - and matching index entries; these are required to provide some of the - cache operations. - - - * In-cache object representation:: - - struct fscache_object { - int debug_id; - enum { - FSCACHE_OBJECT_RECYCLING, - ... - } state; - spinlock_t lock - struct fscache_cache *cache; - struct fscache_cookie *cookie; + struct fscache_cache { + void *cache_priv; + unsigned int debug_id; + char *name; ... }; - Structures of this type should be allocated by the cache backend and - passed to FS-Cache when requested by the appropriate cache operation. In - the case of CacheFS, they're embedded in CacheFS's internal object - structures. +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. - The debug_id is a simple integer that can be used in debugging messages - that refer to a particular object. In such a case it should be printed - using "OBJ%x" to be consistent with FS-Cache. - Each object contains a pointer to the cookie that represents the object it - is backing. An object should retired when put_object() is called if it is - in state FSCACHE_OBJECT_RECYCLING. The fscache_object struct should be - initialised by calling fscache_object_init(object). +Registering a Cache +=================== +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:: - * FS-Cache operation record:: + struct fscache_cache *fscache_acquire_cache(const char *name); - struct fscache_operation { - atomic_t usage; - struct fscache_object *object; - unsigned long flags; - #define FSCACHE_OP_EXCLUSIVE - void (*processor)(struct fscache_operation *op); - void (*release)(struct fscache_operation *op); - ... - }; +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. - FS-Cache has a pool of threads that it uses to give CPU time to the - various asynchronous operations that need to be done as part of driving - the cache. These are represented by the above structure. The processor - method is called to give the op CPU time, and the release method to get - rid of it when its usage count reaches 0. +If successful, the cache backend can then start setting up the cache. In the +event that the initialisation fails, the cache backend should call:: - An operation can be made exclusive upon an object by setting the - appropriate flag before enqueuing it with fscache_enqueue_operation(). If - an operation needs more processing time, it should be enqueued again. + void fscache_relinquish_cookie(struct fscache_cache *cache); +to reset and discard the cookie. - * FS-Cache retrieval operation record:: - struct fscache_retrieval { - struct fscache_operation op; - struct address_space *mapping; - struct list_head *to_do; - ... - }; +Bringing a Cache Online +======================= - A structure of this type is allocated by FS-Cache to record retrieval and - allocation requests made by the netfs. This struct is then passed to the - backend to do the operation. The backend may get extra refs to it by - calling fscache_get_retrieval() and refs may be discarded by calling - fscache_put_retrieval(). +Once the cache is set up, it can be brought online by calling:: - A retrieval operation can be used by the backend to do retrieval work. To - do this, the retrieval->op.processor method pointer should be set - appropriately by the backend and fscache_enqueue_retrieval() called to - submit it to the thread pool. CacheFiles, for example, uses this to queue - page examination when it detects PG_lock being cleared. + int fscache_add_cache(struct fscache_cache *cache, + const struct fscache_cache_ops *ops, + void *cache_priv); - The to_do field is an empty list available for the cache backend to use as - it sees fit. +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. - * FS-Cache storage operation record:: +Withdrawing a Cache From Service +================================ - struct fscache_storage { - struct fscache_operation op; - pgoff_t store_limit; - ... - }; +The cache backend can withdraw a cache from service by calling this function:: - A structure of this type is allocated by FS-Cache to record outstanding - writes to be made. FS-Cache itself enqueues this operation and invokes - the write_page() method on the object at appropriate times to effect - storage. + void fscache_withdraw_cache(struct fscache_cache *cache); +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. -Cache Operations -================ +The cache must then go through the data storage objects it has and tell fscache +to withdraw them, calling:: -The cache backend provides FS-Cache with a table of operations that can be -performed on the denizens of the cache. These are held in a structure of type: + void fscache_withdraw_cookie(struct fscache_cookie *cookie); - :: +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 +test for completion by calling:: - struct fscache_cache_ops + bool fscache_are_objects_withdrawn(struct fscache_cookie *cache); - * Name of cache provider [mandatory]:: +Once all the cookies are withdrawn, a cache backend can withdraw all the +volumes, calling:: - const char *name + void fscache_withdraw_volume(struct fscache_volume *volume); - This isn't strictly an operation, but should be pointed at a string naming - the backend. +to tell fscache that a volume has been withdrawn. This waits for all +outstanding accesses on the volume to complete before returning. +When the the cache is completely withdrawn, fscache should be notified by +calling:: - * Allocate a new object [mandatory]:: + void fscache_cache_relinquish(struct fscache_cache *cache); - struct fscache_object *(*alloc_object)(struct fscache_cache *cache, - struct fscache_cookie *cookie) +to clear fields in the cookie and discard the caller's ref on it. - This method is used to allocate a cache object representation to back a - cookie in a particular cache. fscache_object_init() should be called on - the object to initialise it prior to returning. - This function may also be used to parse the index key to be used for - multiple lookup calls to turn it into a more convenient form. FS-Cache - will call the lookup_complete() method to allow the cache to release the - form once lookup is complete or aborted. +Volume Cookies +============== +Within a cache, the data storage objects are organised into logical volumes. +These are represented in the API as objects of type:: - * Look up and create object [mandatory]:: + 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[]; + }; - void (*lookup_object)(struct fscache_object *object) +There are a number of fields here that are of interest to the caching backend: - This method is used to look up an object, given that the object is already - allocated and attached to the cookie. This should instantiate that object - in the cache if it can. + * ``cache`` - The parent cache cookie. - The method should call fscache_object_lookup_negative() as soon as - possible if it determines the object doesn't exist in the cache. If the - object is found to exist and the netfs indicates that it is valid then - fscache_obtained_object() should be called once the object is in a - position to have data stored in it. Similarly, fscache_obtained_object() - should also be called once a non-present object has been created. + * ``cache_priv`` - A place for the cache to stash private data. - If a lookup error occurs, fscache_object_lookup_error() should be called - to abort the lookup of that object. + * ``debug_id`` - A debugging ID for logging in tracepoints. + * ``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. - * Release lookup data [mandatory]:: + * ``key_hash`` - A hash of the index key. This should work out the same, no + matter the cpu arch and endianness. - void (*lookup_complete)(struct fscache_object *object) + * ``coherency`` - A piece of coherency data that should be checked when the + volume is bound to in the cache. - This method is called to ask the cache to release any resources it was - using to perform a lookup. + * ``coherency_len`` - The amount of data in the coherency buffer. - * Increment object refcount [mandatory]:: +Data Storage Cookies +==================== - struct fscache_object *(*grab_object)(struct fscache_object *object) +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:: - This method is called to increment the reference count on an object. It - may fail (for instance if the cache is being withdrawn) by returning NULL. - It should return the object pointer if successful. + 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; + ... + }; +The fields in the cookie that are of interest to the cache backend are: - * Lock/Unlock object [mandatory]:: + * ``volume`` - The parent volume cookie. - void (*lock_object)(struct fscache_object *object) - void (*unlock_object)(struct fscache_object *object) + * ``cache_priv`` - A place for the cache to stash private data. - These methods are used to exclusively lock an object. It must be possible - to schedule with the lock held, so a spinlock isn't sufficient. + * ``flags`` - A collection of bit flags, including: + * 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. - * Pin/Unpin object [optional]:: + * FSCACHE_COOKIE_NEEDS_UPDATE - The coherency data and/or object size has + been changed and needs committing. - int (*pin_object)(struct fscache_object *object) - void (*unpin_object)(struct fscache_object *object) + * 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. - These methods are used to pin an object into the cache. Once pinned an - object cannot be reclaimed to make space. Return -ENOSPC if there's not - enough space in the cache to permit this. + * FSCACHE_COOKIE_HAVE_DATA - The backend should set this if it + successfully stores data into the cache. + * FSCACHE_COOKIE_RETIRED - The cookie was invalidated when it was + relinquished and the cached data should be discarded. - * Check coherency state of an object [mandatory]:: + * ``debug_id`` - A debugging ID for logging in tracepoints. - int (*check_consistency)(struct fscache_object *object) + * ``inval_counter`` - The number of invalidations done on the cookie. - This method is called to have the cache check the saved auxiliary data of - the object against the netfs's idea of the state. 0 should be returned - if they're consistent and -ESTALE otherwise. -ENOMEM and -ERESTARTSYS - may also be returned. + * ``advice`` - Information about how the cookie is to be used. - * Update object [mandatory]:: + * ``key_hash`` - A hash of the index key. This should work out the same, no + matter the cpu arch and endianness. - int (*update_object)(struct fscache_object *object) + * ``key_len`` - The length of the index key. - This is called to update the index entry for the specified object. The - new information should be in object->cookie->netfs_data. This can be - obtained by calling object->cookie->def->get_aux()/get_attr(). + * ``aux_len`` - The length of the coherency data buffer. +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:: - * Invalidate data object [mandatory]:: + void *fscache_get_key(struct fscache_cookie *cookie); - int (*invalidate_object)(struct fscache_operation *op) +The index key is a binary blob, the storage for which is padded out to a +multiple of 4 bytes. - This is called to invalidate a data object (as pointed to by op->object). - All the data stored for this object should be discarded and an - attr_changed operation should be performed. The caller will follow up - with an object update operation. +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:: - fscache_op_complete() must be called on op before returning. + void *fscache_get_aux(struct fscache_cookie *cookie); - * Discard object [mandatory]:: - void (*drop_object)(struct fscache_object *object) +Cookie Accounting +================= - This method is called to indicate that an object has been unbound from its - cookie, and that the cache should release the object's resources and - retire it if it's in state FSCACHE_OBJECT_RECYCLING. +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:: - This method should not attempt to release any references held by the - caller. The caller will invoke the put_object() method as appropriate. + 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); +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. - * Release object reference [mandatory]:: +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. - void (*put_object)(struct fscache_object *object) - This method is used to discard a reference to an object. The object may - be freed when all the references to it are released. +Cache Management API +==================== +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:: - * Synchronise a cache [mandatory]:: + struct fscache_cache_ops { + const char *name; + ... + }; - void (*sync)(struct fscache_cache *cache) +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: - This is called to ask the backend to synchronise a cache with its backing - device. + * Set up a volume cookie [optional]:: + void (*acquire_volume)(struct fscache_volume *volume); - * Dissociate a cache [mandatory]:: + 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. - void (*dissociate_pages)(struct fscache_cache *cache) + If successful, it can set ``cache_priv`` to its own data. - This is called to ask a cache to perform any page dissociations as part of - cache withdrawal. + * Clean up volume cookie [optional]:: - * Notification that the attributes on a netfs file changed [mandatory]:: + void (*free_volume)(struct fscache_volume *volume); - int (*attr_changed)(struct fscache_object *object); + This method is called when a volume cookie is being released if + ``cache_priv`` is set. - This is called to indicate to the cache that certain attributes on a netfs - file have changed (for example the maximum size a file may reach). The - cache can read these from the netfs by calling the cookie's get_attr() - method. - The cache may use the file size information to reserve space on the cache. - It should also call fscache_set_store_limit() to indicate to FS-Cache the - highest byte it's willing to store for an object. + * Look up a cookie in the cache [mandatory]:: - This method may return -ve if an error occurred or the cache object cannot - be expanded. In such a case, the object will be withdrawn from service. + bool (*lookup_cookie)(struct fscache_cookie *cookie); - This operation is run asynchronously from FS-Cache's thread pool, and - storage and retrieval operations from the netfs are excluded during the - execution of this operation. + 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. + True should be returned if successful and false otherwise. If false is + returned, the withdraw_cookie op (see below) will be called. - * Reserve cache space for an object's data [optional]:: + If lookup fails, but the object could still be created (e.g. it hasn't + been cached before), then:: - int (*reserve_space)(struct fscache_object *object, loff_t size); + void fscache_cookie_lookup_negative( + struct fscache_cookie *cookie); - This is called to request that cache space be reserved to hold the data - for an object and the metadata used to track it. Zero size should be - taken as request to cancel a reservation. + 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. - This should return 0 if successful, -ENOSPC if there isn't enough space - available, or -ENOMEM or -EIO on other errors. + If successful, ``cookie->cache_priv`` can be set. - The reservation may exceed the current size of the object, thus permitting - future expansion. If the amount of space consumed by an object would - exceed the reservation, it's permitted to refuse requests to allocate - pages, but not required. An object may be pruned down to its reservation - size if larger than that already. + * Withdraw an object without any cookie access counts held [mandatory]:: - * Request page be read from cache [mandatory]:: + void (*withdraw_cookie)(struct fscache_cookie *cookie); - int (*read_or_alloc_page)(struct fscache_retrieval *op, - struct page *page, - gfp_t gfp) + 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. - This is called to attempt to read a netfs page from the cache, or to - reserve a backing block if not. FS-Cache will have done as much checking - as it can before calling, but most of the work belongs to the backend. + 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. - If there's no page in the cache, then -ENODATA should be returned if the - backend managed to reserve a backing block; -ENOBUFS or -ENOMEM if it - didn't. + The cookie will have the ``FSCACHE_COOKIE_RETIRED`` flag set on it if the + associated data is to be removed from the cache. - If there is suitable data in the cache, then a read operation should be - queued and 0 returned. When the read finishes, fscache_end_io() should be - called. - The fscache_mark_pages_cached() should be called for the page if any cache - metadata is retained. This will indicate to the netfs that the page needs - explicit uncaching. This operation takes a pagevec, thus allowing several - pages to be marked at once. + * Change the size of a data storage object [mandatory]:: - The retrieval record pointed to by op should be retained for each page - queued and released when I/O on the page has been formally ended. - fscache_get/put_retrieval() are available for this purpose. + void (*resize_cookie)(struct netfs_cache_resources *cres, + loff_t new_size); - The retrieval record may be used to get CPU time via the FS-Cache thread - pool. If this is desired, the op->op.processor should be set to point to - the appropriate processing routine, and fscache_enqueue_retrieval() should - be called at an appropriate point to request CPU time. For instance, the - retrieval routine could be enqueued upon the completion of a disk read. - The to_do field in the retrieval record is provided to aid in this. + 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. - If an I/O error occurs, fscache_io_error() should be called and -ENOBUFS - returned if possible or fscache_end_io() called with a suitable error - code. + 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. - fscache_put_retrieval() should be called after a page or pages are dealt - with. This will complete the operation when all pages are dealt with. + * Invalidate a data storage object [mandatory]:: - * Request pages be read from cache [mandatory]:: + bool (*invalidate_cookie)(struct fscache_cookie *cookie); - int (*read_or_alloc_pages)(struct fscache_retrieval *op, - struct list_head *pages, - unsigned *nr_pages, - gfp_t gfp) + 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. - This is like the read_or_alloc_page() method, except it is handed a list - of pages instead of one page. Any pages on which a read operation is - started must be added to the page cache for the specified mapping and also - to the LRU. Such pages must also be removed from the pages list and - ``*nr_pages`` decremented per page. + 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:: - If there was an error such as -ENOMEM, then that should be returned; else - if one or more pages couldn't be read or allocated, then -ENOBUFS should - be returned; else if one or more pages couldn't be read, then -ENODATA - should be returned. If all the pages are dispatched then 0 should be - returned. + void fscache_resume_after_invalidation(struct fscache_cookie *cookie); + If the method returns false, caching will be withdrawn for this cookie. - * Request page be allocated in the cache [mandatory]:: - int (*allocate_page)(struct fscache_retrieval *op, - struct page *page, - gfp_t gfp) + * Prepare to make local modifications to the cache [mandatory]:: - This is like the read_or_alloc_page() method, except that it shouldn't - read from the cache, even if there's data there that could be retrieved. - It should, however, set up any internal metadata required such that - the write_page() method can write to the cache. + void (*prepare_to_write)(struct fscache_cookie *cookie); - If there's no backing block available, then -ENOBUFS should be returned - (or -ENOMEM if there were other problems). If a block is successfully - allocated, then the netfs page should be marked and 0 returned. + 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. - * Request pages be allocated in the cache [mandatory]:: + * Begin an operation for the netfs lib [mandatory]:: - int (*allocate_pages)(struct fscache_retrieval *op, - struct list_head *pages, - unsigned *nr_pages, - gfp_t gfp) + bool (*begin_operation)(struct netfs_cache_resources *cres, + enum fscache_want_state want_state); - This is an multiple page version of the allocate_page() method. pages and - nr_pages should be treated as for the read_or_alloc_pages() method. + 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. + If it can, the backend should attach any resources it needs to keep around + to the netfs_cache_resources object and return true. - * Request page be written to cache [mandatory]:: + If it can't complete the setup, it should return false. - int (*write_page)(struct fscache_storage *op, - struct page *page); + 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: - This is called to write from a page on which there was a previously - successful read_or_alloc_page() call or similar. FS-Cache filters out - pages that don't have mappings. + * ``FSCACHE_WANT_PARAMS`` - The caller just wants to access cache + object parameters; it doesn't need to do data I/O yet. - This method is called asynchronously from the FS-Cache thread pool. It is - not required to actually store anything, provided -ENODATA is then - returned to the next read of this page. + * ``FSCACHE_WANT_READ`` - The caller wants to read data. - If an error occurred, then a negative error code should be returned, - otherwise zero should be returned. FS-Cache will take appropriate action - in response to an error, such as withdrawing this object. + * ``FSCACHE_WANT_WRITE`` - The caller wants to write to or resize the + cache object. - If this method returns success then FS-Cache will inform the netfs - appropriately. + Note that there won't necessarily be anything attached to the cookie's + cache_priv yet if the cookie is still being created. - * Discard retained per-page metadata [mandatory]:: +Data I/O API +============ - void (*uncache_page)(struct fscache_object *object, struct page *page) +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. - This is called when a netfs page is being evicted from the pagecache. The - cache backend should tear down any internal representation or tracking it - maintains for this page. +See the Documentation/filesystems/netfs_library.rst for a description. -FS-Cache Utilities -================== +Miscellaneous Functions +======================= FS-Cache provides some utilities that a cache backend may make use of: * Note occurrence of an I/O error in a cache:: - void fscache_io_error(struct fscache_cache *cache) + void fscache_io_error(struct fscache_cache *cache); - This tells FS-Cache that an I/O error occurred in the cache. After this - has been called, only resource dissociation operations (object and page - release) will be passed from the netfs to the cache backend for the - specified cache. + 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. This does not actually withdraw the cache. That must be done separately. + * Note cessation of caching on a cookie due to failure:: - * Invoke the retrieval I/O completion function:: - - void fscache_end_io(struct fscache_retrieval *op, struct page *page, - int error); - - This is called to note the end of an attempt to retrieve a page. The - error value should be 0 if successful and an error otherwise. - - - * Record that one or more pages being retrieved or allocated have been dealt - with:: - - void fscache_retrieval_complete(struct fscache_retrieval *op, - int n_pages); - - This is called to record the fact that one or more pages have been dealt - with and are no longer the concern of this operation. When the number of - pages remaining in the operation reaches 0, the operation will be - completed. - - - * Record operation completion:: - - void fscache_op_complete(struct fscache_operation *op); - - This is called to record the completion of an operation. This deducts - this operation from the parent object's run state, potentially permitting - one or more pending operations to start running. - - - * Set highest store limit:: - - void fscache_set_store_limit(struct fscache_object *object, - loff_t i_size); - - This sets the limit FS-Cache imposes on the highest byte it's willing to - try and store for a netfs. Any page over this limit is automatically - rejected by fscache_read_alloc_page() and co with -ENOBUFS. - - - * Mark pages as being cached:: - - void fscache_mark_pages_cached(struct fscache_retrieval *op, - struct pagevec *pagevec); - - This marks a set of pages as being cached. After this has been called, - the netfs must call fscache_uncache_page() to unmark the pages. - - - * Perform coherency check on an object:: - - enum fscache_checkaux fscache_check_aux(struct fscache_object *object, - const void *data, - uint16_t datalen); - - This asks the netfs to perform a coherency check on an object that has - just been looked up. The cookie attached to the object will determine the - netfs to use. data and datalen should specify where the auxiliary data - retrieved from the cache can be found. - - One of three values will be returned: - - FSCACHE_CHECKAUX_OKAY - The coherency data indicates the object is valid as is. - - FSCACHE_CHECKAUX_NEEDS_UPDATE - The coherency data needs updating, but otherwise the object is - valid. - - FSCACHE_CHECKAUX_OBSOLETE - The coherency data indicates that the object is obsolete and should - be discarded. - - - * Initialise a freshly allocated object:: - - void fscache_object_init(struct fscache_object *object); - - This initialises all the fields in an object representation. - - - * Indicate the destruction of an object:: - - void fscache_object_destroyed(struct fscache_cache *cache); - - This must be called to inform FS-Cache that an object that belonged to a - cache has been destroyed and deallocated. This will allow continuation - of the cache withdrawal process when it is stopped pending destruction of - all the objects. - - - * Indicate negative lookup on an object:: - - void fscache_object_lookup_negative(struct fscache_object *object); - - This is called to indicate to FS-Cache that a lookup process for an object - found a negative result. - - This changes the state of an object to permit reads pending on lookup - completion to go off and start fetching data from the netfs server as it's - known at this point that there can't be any data in the cache. - - This may be called multiple times on an object. Only the first call is - significant - all subsequent calls are ignored. - - - * Indicate an object has been obtained:: - - void fscache_obtained_object(struct fscache_object *object); - - This is called to indicate to FS-Cache that a lookup process for an object - produced a positive result, or that an object was created. This should - only be called once for any particular object. - - This changes the state of an object to indicate: - - (1) if no call to fscache_object_lookup_negative() has been made on - this object, that there may be data available, and that reads can - now go and look for it; and - - (2) that writes may now proceed against this object. - - - * Indicate that object lookup failed:: - - void fscache_object_lookup_error(struct fscache_object *object); - - This marks an object as having encountered a fatal error (usually EIO) - and causes it to move into a state whereby it will be withdrawn as soon - as possible. - - - * Indicate that a stale object was found and discarded:: - - void fscache_object_retrying_stale(struct fscache_object *object); - - This is called to indicate that the lookup procedure found an object in - the cache that the netfs decided was stale. The object has been - discarded from the cache and the lookup will be performed again. - - - * Indicate that the caching backend killed an object:: - - void fscache_object_mark_killed(struct fscache_object *object, - enum fscache_why_object_killed why); - - This is called to indicate that the cache backend preemptively killed an - object. The why parameter should be set to indicate the reason: + void fscache_caching_failed(struct fscache_cookie *cookie); - FSCACHE_OBJECT_IS_STALE - - the object was stale and needs discarding. + 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. - FSCACHE_OBJECT_NO_SPACE - - there was insufficient cache space + * Count I/O requests:: - FSCACHE_OBJECT_WAS_RETIRED - - the object was retired when relinquished. + void fscache_count_read(void); + void fscache_count_write(void); - FSCACHE_OBJECT_WAS_CULLED - - the object was culled to make space. + These record reads and writes from/to the cache. The numbers are + displayed in /proc/fs/fscache/stats. + * Count out-of-space errors:: - * Get and release references on a retrieval record:: + void fscache_count_no_write_space(void); + void fscache_count_no_create_space(void); - void fscache_get_retrieval(struct fscache_retrieval *op); - void fscache_put_retrieval(struct fscache_retrieval *op); + These record ENOSPC errors in the cache, divided into failures of data + writes and failures of filesystem object creations (e.g. mkdir). - These two functions are used to retain a retrieval record while doing - asynchronous data retrieval and block allocation. + * Count objects culled:: + void fscache_count_culled(void); - * Enqueue a retrieval record for processing:: + This records the culling of an object. - void fscache_enqueue_retrieval(struct fscache_retrieval *op); + * Get the cookie from a set of cache resources:: - This enqueues a retrieval record for processing by the FS-Cache thread - pool. One of the threads in the pool will invoke the retrieval record's - op->op.processor callback function. This function may be called from - within the callback function. + struct fscache_cookie *fscache_cres_cookie(struct netfs_cache_resources *cres) + Pull a pointer to the cookie from the cache resources. This may return a + NULL cookie if no cookie was set. - * List of object state names:: - const char *fscache_object_states[]; +API Function Reference +====================== - For debugging purposes, this may be used to turn the state that an object - is in into a text string for display purposes. +.. kernel-doc:: include/linux/fscache-cache.h |