1efc930faSMauro Carvalho Chehab.. SPDX-License-Identifier: GPL-2.0 2efc930faSMauro Carvalho Chehab 3e0484344SDavid Howells============================== 4e0484344SDavid HowellsNetwork Filesystem Caching API 5e0484344SDavid Howells============================== 6efc930faSMauro Carvalho Chehab 7e0484344SDavid HowellsFscache provides an API by which a network filesystem can make use of local 8e0484344SDavid Howellscaching facilities. The API is arranged around a number of principles: 9efc930faSMauro Carvalho Chehab 10e0484344SDavid Howells (1) A cache is logically organised into volumes and data storage objects 11e0484344SDavid Howells within those volumes. 12efc930faSMauro Carvalho Chehab 13e0484344SDavid Howells (2) Volumes and data storage objects are represented by various types of 14e0484344SDavid Howells cookie. 15efc930faSMauro Carvalho Chehab 16e0484344SDavid Howells (3) Cookies have keys that distinguish them from their peers. 17efc930faSMauro Carvalho Chehab 18e0484344SDavid Howells (4) Cookies have coherency data that allows a cache to determine if the 19e0484344SDavid Howells cached data is still valid. 20e0484344SDavid Howells 21e0484344SDavid Howells (5) I/O is done asynchronously where possible. 22e0484344SDavid Howells 23e0484344SDavid HowellsThis API is used by:: 24e0484344SDavid Howells 25e0484344SDavid Howells #include <linux/fscache.h>. 26efc930faSMauro Carvalho Chehab 27efc930faSMauro Carvalho Chehab.. This document contains the following sections: 28efc930faSMauro Carvalho Chehab 29e0484344SDavid Howells (1) Overview 30e0484344SDavid Howells (2) Volume registration 31e0484344SDavid Howells (3) Data file registration 32e0484344SDavid Howells (4) Declaring a cookie to be in use 33e0484344SDavid Howells (5) Resizing a data file (truncation) 34e0484344SDavid Howells (6) Data I/O API 35e0484344SDavid Howells (7) Data file coherency 36e0484344SDavid Howells (8) Data file invalidation 37e0484344SDavid Howells (9) Write back resource management 38e0484344SDavid Howells (10) Caching of local modifications 39e0484344SDavid Howells (11) Page release and invalidation 40efc930faSMauro Carvalho Chehab 41efc930faSMauro Carvalho Chehab 42e0484344SDavid HowellsOverview 43e0484344SDavid Howells======== 44efc930faSMauro Carvalho Chehab 45e0484344SDavid HowellsThe fscache hierarchy is organised on two levels from a network filesystem's 46e0484344SDavid Howellspoint of view. The upper level represents "volumes" and the lower level 47e0484344SDavid Howellsrepresents "data storage objects". These are represented by two types of 48e0484344SDavid Howellscookie, hereafter referred to as "volume cookies" and "cookies". 49efc930faSMauro Carvalho Chehab 50e0484344SDavid HowellsA network filesystem acquires a volume cookie for a volume using a volume key, 51e0484344SDavid Howellswhich represents all the information that defines that volume (e.g. cell name 52e0484344SDavid Howellsor server address, volume ID or share name). This must be rendered as a 53e0484344SDavid Howellsprintable string that can be used as a directory name (ie. no '/' characters 54e0484344SDavid Howellsand shouldn't begin with a '.'). The maximum name length is one less than the 55e0484344SDavid Howellsmaximum size of a filename component (allowing the cache backend one char for 56e0484344SDavid Howellsits own purposes). 57efc930faSMauro Carvalho Chehab 58e0484344SDavid HowellsA filesystem would typically have a volume cookie for each superblock. 59efc930faSMauro Carvalho Chehab 60e0484344SDavid HowellsThe filesystem then acquires a cookie for each file within that volume using an 61e0484344SDavid Howellsobject key. Object keys are binary blobs and only need to be unique within 62*d56b699dSBjorn Helgaastheir parent volume. The cache backend is responsible for rendering the binary 63e0484344SDavid Howellsblob into something it can use and may employ hash tables, trees or whatever to 64e0484344SDavid Howellsimprove its ability to find an object. This is transparent to the network 65e0484344SDavid Howellsfilesystem. 66efc930faSMauro Carvalho Chehab 67e0484344SDavid HowellsA filesystem would typically have a cookie for each inode, and would acquire it 68e0484344SDavid Howellsin iget and relinquish it when evicting the cookie. 69efc930faSMauro Carvalho Chehab 70e0484344SDavid HowellsOnce it has a cookie, the filesystem needs to mark the cookie as being in use. 71e0484344SDavid HowellsThis causes fscache to send the cache backend off to look up/create resources 72e0484344SDavid Howellsfor the cookie in the background, to check its coherency and, if necessary, to 73e0484344SDavid Howellsmark the object as being under modification. 74efc930faSMauro Carvalho Chehab 75e0484344SDavid HowellsA filesystem would typically "use" the cookie in its file open routine and 76e0484344SDavid Howellsunuse it in file release and it needs to use the cookie around calls to 77e0484344SDavid Howellstruncate the cookie locally. It *also* needs to use the cookie when the 78e0484344SDavid Howellspagecache becomes dirty and unuse it when writeback is complete. This is 79e0484344SDavid Howellsslightly tricky, and provision is made for it. 80efc930faSMauro Carvalho Chehab 81e0484344SDavid HowellsWhen performing a read, write or resize on a cookie, the filesystem must first 82e0484344SDavid Howellsbegin an operation. This copies the resources into a holding struct and puts 83e0484344SDavid Howellsextra pins into the cache to stop cache withdrawal from tearing down the 84e0484344SDavid Howellsstructures being used. The actual operation can then be issued and conflicting 85e0484344SDavid Howellsinvalidations can be detected upon completion. 86efc930faSMauro Carvalho Chehab 87e0484344SDavid HowellsThe filesystem is expected to use netfslib to access the cache, but that's not 88e0484344SDavid Howellsactually required and it can use the fscache I/O API directly. 89efc930faSMauro Carvalho Chehab 90efc930faSMauro Carvalho Chehab 91e0484344SDavid HowellsVolume Registration 92e0484344SDavid Howells=================== 93efc930faSMauro Carvalho Chehab 94*d56b699dSBjorn HelgaasThe first step for a network filesystem is to acquire a volume cookie for the 95e0484344SDavid Howellsvolume it wants to access:: 96efc930faSMauro Carvalho Chehab 97e0484344SDavid Howells struct fscache_volume * 98e0484344SDavid Howells fscache_acquire_volume(const char *volume_key, 99e0484344SDavid Howells const char *cache_name, 100e0484344SDavid Howells const void *coherency_data, 101e0484344SDavid Howells size_t coherency_len); 102efc930faSMauro Carvalho Chehab 103e0484344SDavid HowellsThis function creates a volume cookie with the specified volume key as its name 104e0484344SDavid Howellsand notes the coherency data. 105efc930faSMauro Carvalho Chehab 106e0484344SDavid HowellsThe volume key must be a printable string with no '/' characters in it. It 107e0484344SDavid Howellsshould begin with the name of the filesystem and should be no longer than 254 108e0484344SDavid Howellscharacters. It should uniquely represent the volume and will be matched with 109e0484344SDavid Howellswhat's stored in the cache. 110efc930faSMauro Carvalho Chehab 111e0484344SDavid HowellsThe caller may also specify the name of the cache to use. If specified, 112e0484344SDavid Howellsfscache will look up or create a cache cookie of that name and will use a cache 113e0484344SDavid Howellsof that name if it is online or comes online. If no cache name is specified, 114e0484344SDavid Howellsit will use the first cache that comes to hand and set the name to that. 115efc930faSMauro Carvalho Chehab 116e0484344SDavid HowellsThe specified coherency data is stored in the cookie and will be matched 117e0484344SDavid Howellsagainst coherency data stored on disk. The data pointer may be NULL if no data 118e0484344SDavid Howellsis provided. If the coherency data doesn't match, the entire cache volume will 119e0484344SDavid Howellsbe invalidated. 120efc930faSMauro Carvalho Chehab 121e0484344SDavid HowellsThis function can return errors such as EBUSY if the volume key is already in 122*d56b699dSBjorn Helgaasuse by an acquired volume or ENOMEM if an allocation failure occurred. It may 123e0484344SDavid Howellsalso return a NULL volume cookie if fscache is not enabled. It is safe to 124e0484344SDavid Howellspass a NULL cookie to any function that takes a volume cookie. This will 125e0484344SDavid Howellscause that function to do nothing. 126efc930faSMauro Carvalho Chehab 127efc930faSMauro Carvalho Chehab 128e0484344SDavid HowellsWhen the network filesystem has finished with a volume, it should relinquish it 129e0484344SDavid Howellsby calling:: 130efc930faSMauro Carvalho Chehab 131e0484344SDavid Howells void fscache_relinquish_volume(struct fscache_volume *volume, 132e0484344SDavid Howells const void *coherency_data, 133e0484344SDavid Howells bool invalidate); 134efc930faSMauro Carvalho Chehab 135e0484344SDavid HowellsThis will cause the volume to be committed or removed, and if sealed the 136e0484344SDavid Howellscoherency data will be set to the value supplied. The amount of coherency data 137e0484344SDavid Howellsmust match the length specified when the volume was acquired. Note that all 138e0484344SDavid Howellsdata cookies obtained in this volume must be relinquished before the volume is 139e0484344SDavid Howellsrelinquished. 140efc930faSMauro Carvalho Chehab 141efc930faSMauro Carvalho Chehab 142efc930faSMauro Carvalho ChehabData File Registration 143efc930faSMauro Carvalho Chehab====================== 144efc930faSMauro Carvalho Chehab 145e0484344SDavid HowellsOnce it has a volume cookie, a network filesystem can use it to acquire a 146e0484344SDavid Howellscookie for data storage:: 147efc930faSMauro Carvalho Chehab 148e0484344SDavid Howells struct fscache_cookie * 149e0484344SDavid Howells fscache_acquire_cookie(struct fscache_volume *volume, 150e0484344SDavid Howells u8 advice, 151e0484344SDavid Howells const void *index_key, 152e0484344SDavid Howells size_t index_key_len, 153efc930faSMauro Carvalho Chehab const void *aux_data, 154e0484344SDavid Howells size_t aux_data_len, 155e0484344SDavid Howells loff_t object_size) 156efc930faSMauro Carvalho Chehab 157e0484344SDavid HowellsThis creates the cookie in the volume using the specified index key. The index 158e0484344SDavid Howellskey is a binary blob of the given length and must be unique for the volume. 159e0484344SDavid HowellsThis is saved into the cookie. There are no restrictions on the content, but 160e0484344SDavid Howellsits length shouldn't exceed about three quarters of the maximum filename length 161e0484344SDavid Howellsto allow for encoding. 162efc930faSMauro Carvalho Chehab 163e0484344SDavid HowellsThe caller should also pass in a piece of coherency data in aux_data. A buffer 164e0484344SDavid Howellsof size aux_data_len will be allocated and the coherency data copied in. It is 165e0484344SDavid Howellsassumed that the size is invariant over time. The coherency data is used to 166e0484344SDavid Howellscheck the validity of data in the cache. Functions are provided by which the 167e0484344SDavid Howellscoherency data can be updated. 168efc930faSMauro Carvalho Chehab 169e0484344SDavid HowellsThe file size of the object being cached should also be provided. This may be 170e0484344SDavid Howellsused to trim the data and will be stored with the coherency data. 171efc930faSMauro Carvalho Chehab 172e0484344SDavid HowellsThis function never returns an error, though it may return a NULL cookie on 173e0484344SDavid Howellsallocation failure or if fscache is not enabled. It is safe to pass in a NULL 174e0484344SDavid Howellsvolume cookie and pass the NULL cookie returned to any function that takes it. 175e0484344SDavid HowellsThis will cause that function to do nothing. 176efc930faSMauro Carvalho Chehab 177efc930faSMauro Carvalho Chehab 178e0484344SDavid HowellsWhen the network filesystem has finished with a cookie, it should relinquish it 179e0484344SDavid Howellsby calling:: 180efc930faSMauro Carvalho Chehab 181efc930faSMauro Carvalho Chehab void fscache_relinquish_cookie(struct fscache_cookie *cookie, 182efc930faSMauro Carvalho Chehab bool retire); 183efc930faSMauro Carvalho Chehab 184e0484344SDavid HowellsThis will cause fscache to either commit the storage backing the cookie or 185e0484344SDavid Howellsdelete it. 186efc930faSMauro Carvalho Chehab 187efc930faSMauro Carvalho Chehab 188e0484344SDavid HowellsMarking A Cookie In-Use 189e0484344SDavid Howells======================= 190efc930faSMauro Carvalho Chehab 191e0484344SDavid HowellsOnce a cookie has been acquired by a network filesystem, the filesystem should 192e0484344SDavid Howellstell fscache when it intends to use the cookie (typically done on file open) 193e0484344SDavid Howellsand should say when it has finished with it (typically on file close):: 194e0484344SDavid Howells 195e0484344SDavid Howells void fscache_use_cookie(struct fscache_cookie *cookie, 196e0484344SDavid Howells bool will_modify); 197e0484344SDavid Howells void fscache_unuse_cookie(struct fscache_cookie *cookie, 198e0484344SDavid Howells const void *aux_data, 199e0484344SDavid Howells const loff_t *object_size); 200e0484344SDavid Howells 201e0484344SDavid HowellsThe *use* function tells fscache that it will use the cookie and, additionally, 202e0484344SDavid Howellsindicate if the user is intending to modify the contents locally. If not yet 203e0484344SDavid Howellsdone, this will trigger the cache backend to go and gather the resources it 204e0484344SDavid Howellsneeds to access/store data in the cache. This is done in the background, and 205e0484344SDavid Howellsso may not be complete by the time the function returns. 206e0484344SDavid Howells 207e0484344SDavid HowellsThe *unuse* function indicates that a filesystem has finished using a cookie. 208e0484344SDavid HowellsIt optionally updates the stored coherency data and object size and then 209e0484344SDavid Howellsdecreases the in-use counter. When the last user unuses the cookie, it is 210e0484344SDavid Howellsscheduled for garbage collection. If not reused within a short time, the 211e0484344SDavid Howellsresources will be released to reduce system resource consumption. 212e0484344SDavid Howells 213e0484344SDavid HowellsA cookie must be marked in-use before it can be accessed for read, write or 214e0484344SDavid Howellsresize - and an in-use mark must be kept whilst there is dirty data in the 215e0484344SDavid Howellspagecache in order to avoid an oops due to trying to open a file during process 216e0484344SDavid Howellsexit. 217e0484344SDavid Howells 218e0484344SDavid HowellsNote that in-use marks are cumulative. For each time a cookie is marked 219e0484344SDavid Howellsin-use, it must be unused. 220e0484344SDavid Howells 221e0484344SDavid Howells 222e0484344SDavid HowellsResizing A Data File (Truncation) 223e0484344SDavid Howells================================= 224e0484344SDavid Howells 225e0484344SDavid HowellsIf a network filesystem file is resized locally by truncation, the following 226e0484344SDavid Howellsshould be called to notify the cache:: 227e0484344SDavid Howells 228e0484344SDavid Howells void fscache_resize_cookie(struct fscache_cookie *cookie, 229e0484344SDavid Howells loff_t new_size); 230e0484344SDavid Howells 231e0484344SDavid HowellsThe caller must have first marked the cookie in-use. The cookie and the new 232e0484344SDavid Howellssize are passed in and the cache is synchronously resized. This is expected to 233e0484344SDavid Howellsbe called from ``->setattr()`` inode operation under the inode lock. 234e0484344SDavid Howells 235e0484344SDavid Howells 236e0484344SDavid HowellsData I/O API 237e0484344SDavid Howells============ 238e0484344SDavid Howells 239e0484344SDavid HowellsTo do data I/O operations directly through a cookie, the following functions 240e0484344SDavid Howellsare available:: 241e0484344SDavid Howells 242e0484344SDavid Howells int fscache_begin_read_operation(struct netfs_cache_resources *cres, 243e0484344SDavid Howells struct fscache_cookie *cookie); 244e0484344SDavid Howells int fscache_read(struct netfs_cache_resources *cres, 245e0484344SDavid Howells loff_t start_pos, 246e0484344SDavid Howells struct iov_iter *iter, 247e0484344SDavid Howells enum netfs_read_from_hole read_hole, 248e0484344SDavid Howells netfs_io_terminated_t term_func, 249e0484344SDavid Howells void *term_func_priv); 250e0484344SDavid Howells int fscache_write(struct netfs_cache_resources *cres, 251e0484344SDavid Howells loff_t start_pos, 252e0484344SDavid Howells struct iov_iter *iter, 253e0484344SDavid Howells netfs_io_terminated_t term_func, 254e0484344SDavid Howells void *term_func_priv); 255e0484344SDavid Howells 256e0484344SDavid HowellsThe *begin* function sets up an operation, attaching the resources required to 257e0484344SDavid Howellsthe cache resources block from the cookie. Assuming it doesn't return an error 258e0484344SDavid Howells(for instance, it will return -ENOBUFS if given a NULL cookie, but otherwise do 259e0484344SDavid Howellsnothing), then one of the other two functions can be issued. 260e0484344SDavid Howells 261e0484344SDavid HowellsThe *read* and *write* functions initiate a direct-IO operation. Both take the 262e0484344SDavid Howellspreviously set up cache resources block, an indication of the start file 263e0484344SDavid Howellsposition, and an I/O iterator that describes buffer and indicates the amount of 264e0484344SDavid Howellsdata. 265e0484344SDavid Howells 266e0484344SDavid HowellsThe read function also takes a parameter to indicate how it should handle a 267e0484344SDavid Howellspartially populated region (a hole) in the disk content. This may be to ignore 268e0484344SDavid Howellsit, skip over an initial hole and place zeros in the buffer or give an error. 269e0484344SDavid Howells 270e0484344SDavid HowellsThe read and write functions can be given an optional termination function that 271e0484344SDavid Howellswill be run on completion:: 272e0484344SDavid Howells 273e0484344SDavid Howells typedef 274e0484344SDavid Howells void (*netfs_io_terminated_t)(void *priv, ssize_t transferred_or_error, 275e0484344SDavid Howells bool was_async); 276e0484344SDavid Howells 277e0484344SDavid HowellsIf a termination function is given, the operation will be run asynchronously 278e0484344SDavid Howellsand the termination function will be called upon completion. If not given, the 279e0484344SDavid Howellsoperation will be run synchronously. Note that in the asynchronous case, it is 280e0484344SDavid Howellspossible for the operation to complete before the function returns. 281e0484344SDavid Howells 282e0484344SDavid HowellsBoth the read and write functions end the operation when they complete, 283e0484344SDavid Howellsdetaching any pinned resources. 284e0484344SDavid Howells 285e0484344SDavid HowellsThe read operation will fail with ESTALE if invalidation occurred whilst the 286e0484344SDavid Howellsoperation was ongoing. 287e0484344SDavid Howells 288e0484344SDavid Howells 289e0484344SDavid HowellsData File Coherency 290e0484344SDavid Howells=================== 291e0484344SDavid Howells 292e0484344SDavid HowellsTo request an update of the coherency data and file size on a cookie, the 293e0484344SDavid Howellsfollowing should be called:: 294e0484344SDavid Howells 295e0484344SDavid Howells void fscache_update_cookie(struct fscache_cookie *cookie, 296e0484344SDavid Howells const void *aux_data, 297e0484344SDavid Howells const loff_t *object_size); 298e0484344SDavid Howells 299e0484344SDavid HowellsThis will update the cookie's coherency data and/or file size. 300efc930faSMauro Carvalho Chehab 301efc930faSMauro Carvalho Chehab 302efc930faSMauro Carvalho ChehabData File Invalidation 303efc930faSMauro Carvalho Chehab====================== 304efc930faSMauro Carvalho Chehab 305efc930faSMauro Carvalho ChehabSometimes it will be necessary to invalidate an object that contains data. 306e0484344SDavid HowellsTypically this will be necessary when the server informs the network filesystem 307e0484344SDavid Howellsof a remote third-party change - at which point the filesystem has to throw 308e0484344SDavid Howellsaway the state and cached data that it had for an file and reload from the 309e0484344SDavid Howellsserver. 310efc930faSMauro Carvalho Chehab 311e0484344SDavid HowellsTo indicate that a cache object should be invalidated, the following should be 312e0484344SDavid Howellscalled:: 313efc930faSMauro Carvalho Chehab 314e0484344SDavid Howells void fscache_invalidate(struct fscache_cookie *cookie, 315e0484344SDavid Howells const void *aux_data, 316e0484344SDavid Howells loff_t size, 317e0484344SDavid Howells unsigned int flags); 318efc930faSMauro Carvalho Chehab 319e0484344SDavid HowellsThis increases the invalidation counter in the cookie to cause outstanding 320e0484344SDavid Howellsreads to fail with -ESTALE, sets the coherency data and file size from the 321e0484344SDavid Howellsinformation supplied, blocks new I/O on the cookie and dispatches the cache to 322e0484344SDavid Howellsgo and get rid of the old data. 323efc930faSMauro Carvalho Chehab 324e0484344SDavid HowellsInvalidation runs asynchronously in a worker thread so that it doesn't block 325e0484344SDavid Howellstoo much. 326efc930faSMauro Carvalho Chehab 327efc930faSMauro Carvalho Chehab 328e0484344SDavid HowellsWrite-Back Resource Management 329e0484344SDavid Howells============================== 330efc930faSMauro Carvalho Chehab 331e0484344SDavid HowellsTo write data to the cache from network filesystem writeback, the cache 332e0484344SDavid Howellsresources required need to be pinned at the point the modification is made (for 333e0484344SDavid Howellsinstance when the page is marked dirty) as it's not possible to open a file in 334e0484344SDavid Howellsa thread that's exiting. 335efc930faSMauro Carvalho Chehab 336e0484344SDavid HowellsThe following facilities are provided to manage this: 337efc930faSMauro Carvalho Chehab 338e0484344SDavid Howells * An inode flag, ``I_PINNING_FSCACHE_WB``, is provided to indicate that an 339e0484344SDavid Howells in-use is held on the cookie for this inode. It can only be changed if the 340e0484344SDavid Howells the inode lock is held. 341efc930faSMauro Carvalho Chehab 342e0484344SDavid Howells * A flag, ``unpinned_fscache_wb`` is placed in the ``writeback_control`` 343e0484344SDavid Howells struct that gets set if ``__writeback_single_inode()`` clears 344e0484344SDavid Howells ``I_PINNING_FSCACHE_WB`` because all the dirty pages were cleared. 345efc930faSMauro Carvalho Chehab 346e0484344SDavid HowellsTo support this, the following functions are provided:: 347efc930faSMauro Carvalho Chehab 3488fb72b4aSMatthew Wilcox (Oracle) bool fscache_dirty_folio(struct address_space *mapping, 3498fb72b4aSMatthew Wilcox (Oracle) struct folio *folio, 350e0484344SDavid Howells struct fscache_cookie *cookie); 351e0484344SDavid Howells void fscache_unpin_writeback(struct writeback_control *wbc, 352e0484344SDavid Howells struct fscache_cookie *cookie); 353e0484344SDavid Howells void fscache_clear_inode_writeback(struct fscache_cookie *cookie, 354e0484344SDavid Howells struct inode *inode, 355e0484344SDavid Howells const void *aux); 356efc930faSMauro Carvalho Chehab 357e0484344SDavid HowellsThe *set* function is intended to be called from the filesystem's 3588fb72b4aSMatthew Wilcox (Oracle)``dirty_folio`` address space operation. If ``I_PINNING_FSCACHE_WB`` is not 359e0484344SDavid Howellsset, it sets that flag and increments the use count on the cookie (the caller 360e0484344SDavid Howellsmust already have called ``fscache_use_cookie()``). 361efc930faSMauro Carvalho Chehab 362e0484344SDavid HowellsThe *unpin* function is intended to be called from the filesystem's 363e0484344SDavid Howells``write_inode`` superblock operation. It cleans up after writing by unusing 364e0484344SDavid Howellsthe cookie if unpinned_fscache_wb is set in the writeback_control struct. 365e0484344SDavid Howells 366e0484344SDavid HowellsThe *clear* function is intended to be called from the netfs's ``evict_inode`` 367e0484344SDavid Howellssuperblock operation. It must be called *after* 368e0484344SDavid Howells``truncate_inode_pages_final()``, but *before* ``clear_inode()``. This cleans 369e0484344SDavid Howellsup any hanging ``I_PINNING_FSCACHE_WB``. It also allows the coherency data to 370e0484344SDavid Howellsbe updated. 371e0484344SDavid Howells 372e0484344SDavid Howells 373e0484344SDavid HowellsCaching of Local Modifications 374e0484344SDavid Howells============================== 375e0484344SDavid Howells 376e0484344SDavid HowellsIf a network filesystem has locally modified data that it wants to write to the 377e0484344SDavid Howellscache, it needs to mark the pages to indicate that a write is in progress, and 378e0484344SDavid Howellsif the mark is already present, it needs to wait for it to be removed first 379e0484344SDavid Howells(presumably due to an already in-progress operation). This prevents multiple 380e0484344SDavid Howellscompeting DIO writes to the same storage in the cache. 381e0484344SDavid Howells 382e0484344SDavid HowellsFirstly, the netfs should determine if caching is available by doing something 383e0484344SDavid Howellslike:: 384e0484344SDavid Howells 385e0484344SDavid Howells bool caching = fscache_cookie_enabled(cookie); 386e0484344SDavid Howells 387e0484344SDavid HowellsIf caching is to be attempted, pages should be waited for and then marked using 388e0484344SDavid Howellsthe following functions provided by the netfs helper library:: 389e0484344SDavid Howells 390e0484344SDavid Howells void set_page_fscache(struct page *page); 391e0484344SDavid Howells void wait_on_page_fscache(struct page *page); 392e0484344SDavid Howells int wait_on_page_fscache_killable(struct page *page); 393e0484344SDavid Howells 394e0484344SDavid HowellsOnce all the pages in the span are marked, the netfs can ask fscache to 395e0484344SDavid Howellsschedule a write of that region:: 396e0484344SDavid Howells 397e0484344SDavid Howells void fscache_write_to_cache(struct fscache_cookie *cookie, 398e0484344SDavid Howells struct address_space *mapping, 399e0484344SDavid Howells loff_t start, size_t len, loff_t i_size, 400e0484344SDavid Howells netfs_io_terminated_t term_func, 401e0484344SDavid Howells void *term_func_priv, 402e0484344SDavid Howells bool caching) 403e0484344SDavid Howells 404e0484344SDavid HowellsAnd if an error occurs before that point is reached, the marks can be removed 405e0484344SDavid Howellsby calling:: 406e0484344SDavid Howells 4072c547f29SYue Hu void fscache_clear_page_bits(struct address_space *mapping, 408e0484344SDavid Howells loff_t start, size_t len, 409e0484344SDavid Howells bool caching) 410e0484344SDavid Howells 4112c547f29SYue HuIn these functions, a pointer to the mapping to which the source pages are 4122c547f29SYue Huattached is passed in and start and len indicate the size of the region that's 4132c547f29SYue Hugoing to be written (it doesn't have to align to page boundaries necessarily, 4142c547f29SYue Hubut it does have to align to DIO boundaries on the backing filesystem). The 4152c547f29SYue Hucaching parameter indicates if caching should be skipped, and if false, the 4162c547f29SYue Hufunctions do nothing. 417e0484344SDavid Howells 4182c547f29SYue HuThe write function takes some additional parameters: the cookie representing 4192c547f29SYue Huthe cache object to be written to, i_size indicates the size of the netfs file 4202c547f29SYue Huand term_func indicates an optional completion function, to which 4212c547f29SYue Huterm_func_priv will be passed, along with the error or amount written. 422e0484344SDavid Howells 423e0484344SDavid HowellsNote that the write function will always run asynchronously and will unmark all 424e0484344SDavid Howellsthe pages upon completion before calling term_func. 425e0484344SDavid Howells 426e0484344SDavid Howells 427e0484344SDavid HowellsPage Release and Invalidation 428e0484344SDavid Howells============================= 429e0484344SDavid Howells 430e0484344SDavid HowellsFscache keeps track of whether we have any data in the cache yet for a cache 431e0484344SDavid Howellsobject we've just created. It knows it doesn't have to do any reading until it 432e0484344SDavid Howellshas done a write and then the page it wrote from has been released by the VM, 433e0484344SDavid Howellsafter which it *has* to look in the cache. 434e0484344SDavid Howells 435e0484344SDavid HowellsTo inform fscache that a page might now be in the cache, the following function 436fa29000bSMatthew Wilcox (Oracle)should be called from the ``release_folio`` address space op:: 437e0484344SDavid Howells 438e0484344SDavid Howells void fscache_note_page_release(struct fscache_cookie *cookie); 439e0484344SDavid Howells 440fa29000bSMatthew Wilcox (Oracle)if the page has been released (ie. release_folio returned true). 441e0484344SDavid Howells 442e0484344SDavid HowellsPage release and page invalidation should also wait for any mark left on the 443e0484344SDavid Howellspage to say that a DIO write is underway from that page:: 444e0484344SDavid Howells 445e0484344SDavid Howells void wait_on_page_fscache(struct page *page); 446e0484344SDavid Howells int wait_on_page_fscache_killable(struct page *page); 447e0484344SDavid Howells 448e0484344SDavid Howells 449e0484344SDavid HowellsAPI Function Reference 450e0484344SDavid Howells====================== 451e0484344SDavid Howells 452e0484344SDavid Howells.. kernel-doc:: include/linux/fscache.h 453