| ========================== |
| General Filesystem Caching |
| ========================== |
| |
| ======== |
| OVERVIEW |
| ======== |
| |
| This facility is a general purpose cache for network filesystems, though it |
| could be used for caching other things such as ISO9660 filesystems too. |
| |
| FS-Cache mediates between cache backends (such as CacheFS) and network |
| filesystems: |
| |
| +---------+ |
| | | +--------------+ |
| | NFS |--+ | | |
| | | | +-->| CacheFS | |
| +---------+ | +----------+ | | /dev/hda5 | |
| | | | | +--------------+ |
| +---------+ +-->| | | |
| | | | |--+ |
| | AFS |----->| FS-Cache | |
| | | | |--+ |
| +---------+ +-->| | | |
| | | | | +--------------+ |
| +---------+ | +----------+ | | | |
| | | | +-->| CacheFiles | |
| | ISOFS |--+ | /var/cache | |
| | | +--------------+ |
| +---------+ |
| |
| Or to look at it another way, FS-Cache is a module that provides a caching |
| facility to a network filesystem such that the cache is transparent to the |
| user: |
| |
| +---------+ |
| | | |
| | Server | |
| | | |
| +---------+ |
| | NETWORK |
| ~~~~~|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | |
| | +----------+ |
| V | | |
| +---------+ | | |
| | | | | |
| | NFS |----->| FS-Cache | |
| | | | |--+ |
| +---------+ | | | +--------------+ +--------------+ |
| | | | | | | | | |
| V +----------+ +-->| CacheFiles |-->| Ext3 | |
| +---------+ | /var/cache | | /dev/sda6 | |
| | | +--------------+ +--------------+ |
| | VFS | ^ ^ |
| | | | | |
| +---------+ +--------------+ | |
| | KERNEL SPACE | | |
| ~~~~~|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|~~~~~~|~~~~ |
| | USER SPACE | | |
| V | | |
| +---------+ +--------------+ |
| | | | | |
| | Process | | cachefilesd | |
| | | | | |
| +---------+ +--------------+ |
| |
| |
| FS-Cache does not follow the idea of completely loading every netfs file |
| opened in its entirety into a cache before permitting it to be accessed and |
| then serving the pages out of that cache rather than the netfs inode because: |
| |
| (1) It must be practical to operate without a cache. |
| |
| (2) The size of any accessible file must not be limited to the size of the |
| cache. |
| |
| (3) The combined size of all opened files (this includes mapped libraries) |
| must not be limited to the size of the cache. |
| |
| (4) The user should not be forced to download an entire file just to do a |
| one-off access of a small portion of it (such as might be done with the |
| "file" program). |
| |
| It instead serves the cache out in PAGE_SIZE chunks as and when requested by |
| the netfs('s) using it. |
| |
| |
| FS-Cache provides the following facilities: |
| |
| (1) More than one cache can be used at once. Caches can be selected |
| explicitly by use of tags. |
| |
| (2) Caches can be added / removed at any time. |
| |
| (3) The netfs is provided with an interface that allows either party to |
| withdraw caching facilities from a file (required for (2)). |
| |
| (4) The interface to the netfs returns as few errors as possible, preferring |
| rather to let the netfs remain oblivious. |
| |
| (5) Cookies are used to represent indices, files and other objects to the |
| netfs. The simplest cookie is just a NULL pointer - indicating nothing |
| cached there. |
| |
| (6) The netfs is allowed to propose - dynamically - any index hierarchy it |
| desires, though it must be aware that the index search function is |
| recursive, stack space is limited, and indices can only be children of |
| indices. |
| |
| (7) Data I/O is done direct to and from the netfs's pages. The netfs |
| indicates that page A is at index B of the data-file represented by cookie |
| C, and that it should be read or written. The cache backend may or may |
| not start I/O on that page, but if it does, a netfs callback will be |
| invoked to indicate completion. The I/O may be either synchronous or |
| asynchronous. |
| |
| (8) Cookies can be "retired" upon release. At this point FS-Cache will mark |
| them as obsolete and the index hierarchy rooted at that point will get |
| recycled. |
| |
| (9) The netfs provides a "match" function for index searches. In addition to |
| saying whether a match was made or not, this can also specify that an |
| entry should be updated or deleted. |
| |
| (10) As much as possible is done asynchronously. |
| |
| |
| FS-Cache maintains a virtual indexing tree in which all indices, files, objects |
| and pages are kept. Bits of this tree may actually reside in one or more |
| caches. |
| |
| FSDEF |
| | |
| +------------------------------------+ |
| | | |
| NFS AFS |
| | | |
| +--------------------------+ +-----------+ |
| | | | | |
| homedir mirror afs.org redhat.com |
| | | | |
| +------------+ +---------------+ +----------+ |
| | | | | | | |
| 00001 00002 00007 00125 vol00001 vol00002 |
| | | | | | |
| +---+---+ +-----+ +---+ +------+------+ +-----+----+ |
| | | | | | | | | | | | | | |
| PG0 PG1 PG2 PG0 XATTR PG0 PG1 DIRENT DIRENT DIRENT R/W R/O Bak |
| | | |
| PG0 +-------+ |
| | | |
| 00001 00003 |
| | |
| +---+---+ |
| | | | |
| PG0 PG1 PG2 |
| |
| In the example above, you can see two netfs's being backed: NFS and AFS. These |
| have different index hierarchies: |
| |
| (*) The NFS primary index contains per-server indices. Each server index is |
| indexed by NFS file handles to get data file objects. Each data file |
| objects can have an array of pages, but may also have further child |
| objects, such as extended attributes and directory entries. Extended |
| attribute objects themselves have page-array contents. |
| |
| (*) The AFS primary index contains per-cell indices. Each cell index contains |
| per-logical-volume indices. Each of volume index contains up to three |
| indices for the read-write, read-only and backup mirrors of those volumes. |
| Each of these contains vnode data file objects, each of which contains an |
| array of pages. |
| |
| The very top index is the FS-Cache master index in which individual netfs's |
| have entries. |
| |
| Any index object may reside in more than one cache, provided it only has index |
| children. Any index with non-index object children will be assumed to only |
| reside in one cache. |
| |
| |
| The netfs API to FS-Cache can be found in: |
| |
| Documentation/filesystems/caching/netfs-api.txt |
| |
| The cache backend API to FS-Cache can be found in: |
| |
| Documentation/filesystems/caching/backend-api.txt |
| |
| A description of the internal representations and object state machine can be |
| found in: |
| |
| Documentation/filesystems/caching/object.txt |
| |
| |
| ======================= |
| STATISTICAL INFORMATION |
| ======================= |
| |
| If FS-Cache is compiled with the following options enabled: |
| |
| CONFIG_FSCACHE_STATS=y |
| CONFIG_FSCACHE_HISTOGRAM=y |
| |
| then it will gather certain statistics and display them through a number of |
| proc files. |
| |
| (*) /proc/fs/fscache/stats |
| |
| This shows counts of a number of events that can happen in FS-Cache: |
| |
| CLASS EVENT MEANING |
| ======= ======= ======================================================= |
| Cookies idx=N Number of index cookies allocated |
| dat=N Number of data storage cookies allocated |
| spc=N Number of special cookies allocated |
| Objects alc=N Number of objects allocated |
| nal=N Number of object allocation failures |
| avl=N Number of objects that reached the available state |
| ded=N Number of objects that reached the dead state |
| ChkAux non=N Number of objects that didn't have a coherency check |
| ok=N Number of objects that passed a coherency check |
| upd=N Number of objects that needed a coherency data update |
| obs=N Number of objects that were declared obsolete |
| Pages mrk=N Number of pages marked as being cached |
| unc=N Number of uncache page requests seen |
| Acquire n=N Number of acquire cookie requests seen |
| nul=N Number of acq reqs given a NULL parent |
| noc=N Number of acq reqs rejected due to no cache available |
| ok=N Number of acq reqs succeeded |
| nbf=N Number of acq reqs rejected due to error |
| oom=N Number of acq reqs failed on ENOMEM |
| Lookups n=N Number of lookup calls made on cache backends |
| neg=N Number of negative lookups made |
| pos=N Number of positive lookups made |
| crt=N Number of objects created by lookup |
| tmo=N Number of lookups timed out and requeued |
| Updates n=N Number of update cookie requests seen |
| nul=N Number of upd reqs given a NULL parent |
| run=N Number of upd reqs granted CPU time |
| Relinqs n=N Number of relinquish cookie requests seen |
| nul=N Number of rlq reqs given a NULL parent |
| wcr=N Number of rlq reqs waited on completion of creation |
| AttrChg n=N Number of attribute changed requests seen |
| ok=N Number of attr changed requests queued |
| nbf=N Number of attr changed rejected -ENOBUFS |
| oom=N Number of attr changed failed -ENOMEM |
| run=N Number of attr changed ops given CPU time |
| Allocs n=N Number of allocation requests seen |
| ok=N Number of successful alloc reqs |
| wt=N Number of alloc reqs that waited on lookup completion |
| nbf=N Number of alloc reqs rejected -ENOBUFS |
| int=N Number of alloc reqs aborted -ERESTARTSYS |
| ops=N Number of alloc reqs submitted |
| owt=N Number of alloc reqs waited for CPU time |
| abt=N Number of alloc reqs aborted due to object death |
| Retrvls n=N Number of retrieval (read) requests seen |
| ok=N Number of successful retr reqs |
| wt=N Number of retr reqs that waited on lookup completion |
| nod=N Number of retr reqs returned -ENODATA |
| nbf=N Number of retr reqs rejected -ENOBUFS |
| int=N Number of retr reqs aborted -ERESTARTSYS |
| oom=N Number of retr reqs failed -ENOMEM |
| ops=N Number of retr reqs submitted |
| owt=N Number of retr reqs waited for CPU time |
| abt=N Number of retr reqs aborted due to object death |
| Stores n=N Number of storage (write) requests seen |
| ok=N Number of successful store reqs |
| agn=N Number of store reqs on a page already pending storage |
| nbf=N Number of store reqs rejected -ENOBUFS |
| oom=N Number of store reqs failed -ENOMEM |
| ops=N Number of store reqs submitted |
| run=N Number of store reqs granted CPU time |
| pgs=N Number of pages given store req processing time |
| rxd=N Number of store reqs deleted from tracking tree |
| olm=N Number of store reqs over store limit |
| VmScan nos=N Number of release reqs against pages with no pending store |
| gon=N Number of release reqs against pages stored by time lock granted |
| bsy=N Number of release reqs ignored due to in-progress store |
| can=N Number of page stores cancelled due to release req |
| Ops pend=N Number of times async ops added to pending queues |
| run=N Number of times async ops given CPU time |
| enq=N Number of times async ops queued for processing |
| can=N Number of async ops cancelled |
| rej=N Number of async ops rejected due to object lookup/create failure |
| dfr=N Number of async ops queued for deferred release |
| rel=N Number of async ops released |
| gc=N Number of deferred-release async ops garbage collected |
| CacheOp alo=N Number of in-progress alloc_object() cache ops |
| luo=N Number of in-progress lookup_object() cache ops |
| luc=N Number of in-progress lookup_complete() cache ops |
| gro=N Number of in-progress grab_object() cache ops |
| upo=N Number of in-progress update_object() cache ops |
| dro=N Number of in-progress drop_object() cache ops |
| pto=N Number of in-progress put_object() cache ops |
| syn=N Number of in-progress sync_cache() cache ops |
| atc=N Number of in-progress attr_changed() cache ops |
| rap=N Number of in-progress read_or_alloc_page() cache ops |
| ras=N Number of in-progress read_or_alloc_pages() cache ops |
| alp=N Number of in-progress allocate_page() cache ops |
| als=N Number of in-progress allocate_pages() cache ops |
| wrp=N Number of in-progress write_page() cache ops |
| ucp=N Number of in-progress uncache_page() cache ops |
| dsp=N Number of in-progress dissociate_pages() cache ops |
| |
| |
| (*) /proc/fs/fscache/histogram |
| |
| cat /proc/fs/fscache/histogram |
| JIFS SECS OBJ INST OP RUNS OBJ RUNS RETRV DLY RETRIEVLS |
| ===== ===== ========= ========= ========= ========= ========= |
| |
| This shows the breakdown of the number of times each amount of time |
| between 0 jiffies and HZ-1 jiffies a variety of tasks took to run. The |
| columns are as follows: |
| |
| COLUMN TIME MEASUREMENT |
| ======= ======================================================= |
| OBJ INST Length of time to instantiate an object |
| OP RUNS Length of time a call to process an operation took |
| OBJ RUNS Length of time a call to process an object event took |
| RETRV DLY Time between an requesting a read and lookup completing |
| RETRIEVLS Time between beginning and end of a retrieval |
| |
| Each row shows the number of events that took a particular range of times. |
| Each step is 1 jiffy in size. The JIFS column indicates the particular |
| jiffy range covered, and the SECS field the equivalent number of seconds. |
| |
| |
| =========== |
| OBJECT LIST |
| =========== |
| |
| If CONFIG_FSCACHE_OBJECT_LIST is enabled, the FS-Cache facility will maintain a |
| list of all the objects currently allocated and allow them to be viewed |
| through: |
| |
| /proc/fs/fscache/objects |
| |
| This will look something like: |
| |
| [root@andromeda ~]# head /proc/fs/fscache/objects |
| OBJECT PARENT STAT CHLDN OPS OOP IPR EX READS EM EV F S | NETFS_COOKIE_DEF TY FL NETFS_DATA OBJECT_KEY, AUX_DATA |
| ======== ======== ==== ===== === === === == ===== == == = = | ================ == == ================ ================ |
| 17e4b 2 ACTV 0 0 0 0 0 0 7b 4 0 0 | NFS.fh DT 0 ffff88001dd82820 010006017edcf8bbc93b43298fdfbe71e50b57b13a172c0117f38472, e567634700000000000000000000000063f2404a000000000000000000000000c9030000000000000000000063f2404a |
| 1693a 2 ACTV 0 0 0 0 0 0 7b 4 0 0 | NFS.fh DT 0 ffff88002db23380 010006017edcf8bbc93b43298fdfbe71e50b57b1e0162c01a2df0ea6, 420ebc4a000000000000000000000000420ebc4a0000000000000000000000000e1801000000000000000000420ebc4a |
| |
| where the first set of columns before the '|' describe the object: |
| |
| COLUMN DESCRIPTION |
| ======= =============================================================== |
| OBJECT Object debugging ID (appears as OBJ%x in some debug messages) |
| PARENT Debugging ID of parent object |
| STAT Object state |
| CHLDN Number of child objects of this object |
| OPS Number of outstanding operations on this object |
| OOP Number of outstanding child object management operations |
| IPR |
| EX Number of outstanding exclusive operations |
| READS Number of outstanding read operations |
| EM Object's event mask |
| EV Events raised on this object |
| F Object flags |
| S Object work item busy state mask (1:pending 2:running) |
| |
| and the second set of columns describe the object's cookie, if present: |
| |
| COLUMN DESCRIPTION |
| =============== ======================================================= |
| NETFS_COOKIE_DEF Name of netfs cookie definition |
| TY Cookie type (IX - index, DT - data, hex - special) |
| FL Cookie flags |
| NETFS_DATA Netfs private data stored in the cookie |
| OBJECT_KEY Object key } 1 column, with separating comma |
| AUX_DATA Object aux data } presence may be configured |
| |
| The data shown may be filtered by attaching the a key to an appropriate keyring |
| before viewing the file. Something like: |
| |
| keyctl add user fscache:objlist <restrictions> @s |
| |
| where <restrictions> are a selection of the following letters: |
| |
| K Show hexdump of object key (don't show if not given) |
| A Show hexdump of object aux data (don't show if not given) |
| |
| and the following paired letters: |
| |
| C Show objects that have a cookie |
| c Show objects that don't have a cookie |
| B Show objects that are busy |
| b Show objects that aren't busy |
| W Show objects that have pending writes |
| w Show objects that don't have pending writes |
| R Show objects that have outstanding reads |
| r Show objects that don't have outstanding reads |
| S Show objects that have work queued |
| s Show objects that don't have work queued |
| |
| If neither side of a letter pair is given, then both are implied. For example: |
| |
| keyctl add user fscache:objlist KB @s |
| |
| shows objects that are busy, and lists their object keys, but does not dump |
| their auxiliary data. It also implies "CcWwRrSs", but as 'B' is given, 'b' is |
| not implied. |
| |
| By default all objects and all fields will be shown. |
| |
| |
| ========= |
| DEBUGGING |
| ========= |
| |
| If CONFIG_FSCACHE_DEBUG is enabled, the FS-Cache facility can have runtime |
| debugging enabled by adjusting the value in: |
| |
| /sys/module/fscache/parameters/debug |
| |
| This is a bitmask of debugging streams to enable: |
| |
| BIT VALUE STREAM POINT |
| ======= ======= =============================== ======================= |
| 0 1 Cache management Function entry trace |
| 1 2 Function exit trace |
| 2 4 General |
| 3 8 Cookie management Function entry trace |
| 4 16 Function exit trace |
| 5 32 General |
| 6 64 Page handling Function entry trace |
| 7 128 Function exit trace |
| 8 256 General |
| 9 512 Operation management Function entry trace |
| 10 1024 Function exit trace |
| 11 2048 General |
| |
| The appropriate set of values should be OR'd together and the result written to |
| the control file. For example: |
| |
| echo $((1|8|64)) >/sys/module/fscache/parameters/debug |
| |
| will turn on all function entry debugging. |