12874c5fdSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
20dfc41d1SDavid Howells /* General filesystem caching backing cache interface
30dfc41d1SDavid Howells *
42cee6fbbSDavid Howells * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
50dfc41d1SDavid Howells * Written by David Howells ([email protected])
60dfc41d1SDavid Howells *
70dfc41d1SDavid Howells * NOTE!!! See:
80dfc41d1SDavid Howells *
90e822145SMauro Carvalho Chehab * Documentation/filesystems/caching/backend-api.rst
100dfc41d1SDavid Howells *
110dfc41d1SDavid Howells * for a description of the cache backend interface declared here.
120dfc41d1SDavid Howells */
130dfc41d1SDavid Howells
140dfc41d1SDavid Howells #ifndef _LINUX_FSCACHE_CACHE_H
150dfc41d1SDavid Howells #define _LINUX_FSCACHE_CACHE_H
160dfc41d1SDavid Howells
170dfc41d1SDavid Howells #include <linux/fscache.h>
18182d919bSDavid Howells
199549332dSDavid Howells enum fscache_cache_trace;
207f3283abSDavid Howells enum fscache_cookie_trace;
219549332dSDavid Howells enum fscache_access_trace;
22*85b08b31SBaokun Li enum fscache_volume_trace;
239549332dSDavid Howells
249549332dSDavid Howells enum fscache_cache_state {
259549332dSDavid Howells FSCACHE_CACHE_IS_NOT_PRESENT, /* No cache is present for this name */
269549332dSDavid Howells FSCACHE_CACHE_IS_PREPARING, /* A cache is preparing to come live */
279549332dSDavid Howells FSCACHE_CACHE_IS_ACTIVE, /* Attached cache is active and can be used */
289549332dSDavid Howells FSCACHE_CACHE_GOT_IOERROR, /* Attached cache stopped on I/O error */
299549332dSDavid Howells FSCACHE_CACHE_IS_WITHDRAWN, /* Attached cache is being withdrawn */
309549332dSDavid Howells #define NR__FSCACHE_CACHE_STATE (FSCACHE_CACHE_IS_WITHDRAWN + 1)
319549332dSDavid Howells };
329549332dSDavid Howells
339549332dSDavid Howells /*
349549332dSDavid Howells * Cache cookie.
359549332dSDavid Howells */
369549332dSDavid Howells struct fscache_cache {
372e0c76aeSDavid Howells const struct fscache_cache_ops *ops;
389549332dSDavid Howells struct list_head cache_link; /* Link in cache list */
399549332dSDavid Howells void *cache_priv; /* Private cache data (or NULL) */
409549332dSDavid Howells refcount_t ref;
419549332dSDavid Howells atomic_t n_volumes; /* Number of active volumes; */
429549332dSDavid Howells atomic_t n_accesses; /* Number of in-progress accesses on the cache */
439549332dSDavid Howells atomic_t object_count; /* no. of live objects in this cache */
449549332dSDavid Howells unsigned int debug_id;
459549332dSDavid Howells enum fscache_cache_state state;
469549332dSDavid Howells char *name;
479549332dSDavid Howells };
489549332dSDavid Howells
492e0c76aeSDavid Howells /*
502e0c76aeSDavid Howells * cache operations
512e0c76aeSDavid Howells */
522e0c76aeSDavid Howells struct fscache_cache_ops {
532e0c76aeSDavid Howells /* name of cache provider */
542e0c76aeSDavid Howells const char *name;
55bfa22da3SDavid Howells
56bfa22da3SDavid Howells /* Acquire a volume */
57bfa22da3SDavid Howells void (*acquire_volume)(struct fscache_volume *volume);
58bfa22da3SDavid Howells
59bfa22da3SDavid Howells /* Free the cache's data attached to a volume */
60bfa22da3SDavid Howells void (*free_volume)(struct fscache_volume *volume);
615d00e426SDavid Howells
625d00e426SDavid Howells /* Look up a cookie in the cache */
635d00e426SDavid Howells bool (*lookup_cookie)(struct fscache_cookie *cookie);
645d00e426SDavid Howells
655d00e426SDavid Howells /* Withdraw an object without any cookie access counts held */
665d00e426SDavid Howells void (*withdraw_cookie)(struct fscache_cookie *cookie);
675d00e426SDavid Howells
6816a96bdfSDavid Howells /* Change the size of a data object */
6916a96bdfSDavid Howells void (*resize_cookie)(struct netfs_cache_resources *cres,
7016a96bdfSDavid Howells loff_t new_size);
7116a96bdfSDavid Howells
72d24af13eSDavid Howells /* Invalidate an object */
73d24af13eSDavid Howells bool (*invalidate_cookie)(struct fscache_cookie *cookie);
74d24af13eSDavid Howells
75d64f4554SDavid Howells /* Begin an operation for the netfs lib */
76d64f4554SDavid Howells bool (*begin_operation)(struct netfs_cache_resources *cres,
77d64f4554SDavid Howells enum fscache_want_state want_state);
78d64f4554SDavid Howells
795d00e426SDavid Howells /* Prepare to write to a live cache object */
805d00e426SDavid Howells void (*prepare_to_write)(struct fscache_cookie *cookie);
812e0c76aeSDavid Howells };
822e0c76aeSDavid Howells
831e1236b8SDavid Howells extern struct workqueue_struct *fscache_wq;
84cdf262f2SDavid Howells extern wait_queue_head_t fscache_clearance_waiters;
851e1236b8SDavid Howells
869549332dSDavid Howells /*
879549332dSDavid Howells * out-of-line cache backend functions
889549332dSDavid Howells */
899549332dSDavid Howells extern struct rw_semaphore fscache_addremove_sem;
909549332dSDavid Howells extern struct fscache_cache *fscache_acquire_cache(const char *name);
919549332dSDavid Howells extern void fscache_relinquish_cache(struct fscache_cache *cache);
922e0c76aeSDavid Howells extern int fscache_add_cache(struct fscache_cache *cache,
932e0c76aeSDavid Howells const struct fscache_cache_ops *ops,
942e0c76aeSDavid Howells void *cache_priv);
952e0c76aeSDavid Howells extern void fscache_withdraw_cache(struct fscache_cache *cache);
96bfa22da3SDavid Howells extern void fscache_withdraw_volume(struct fscache_volume *volume);
975d00e426SDavid Howells extern void fscache_withdraw_cookie(struct fscache_cookie *cookie);
989549332dSDavid Howells
9929f18e79SDavid Howells extern void fscache_io_error(struct fscache_cache *cache);
10029f18e79SDavid Howells
101*85b08b31SBaokun Li extern struct fscache_volume *
102*85b08b31SBaokun Li fscache_try_get_volume(struct fscache_volume *volume,
103*85b08b31SBaokun Li enum fscache_volume_trace where);
104*85b08b31SBaokun Li extern void fscache_put_volume(struct fscache_volume *volume,
105*85b08b31SBaokun Li enum fscache_volume_trace where);
106e6acd329SDavid Howells extern void fscache_end_volume_access(struct fscache_volume *volume,
107e6acd329SDavid Howells struct fscache_cookie *cookie,
108e6acd329SDavid Howells enum fscache_access_trace why);
109e6acd329SDavid Howells
1107f3283abSDavid Howells extern struct fscache_cookie *fscache_get_cookie(struct fscache_cookie *cookie,
1117f3283abSDavid Howells enum fscache_cookie_trace where);
1127f3283abSDavid Howells extern void fscache_put_cookie(struct fscache_cookie *cookie,
1137f3283abSDavid Howells enum fscache_cookie_trace where);
114a7733fb6SDavid Howells extern void fscache_end_cookie_access(struct fscache_cookie *cookie,
115a7733fb6SDavid Howells enum fscache_access_trace why);
1165d00e426SDavid Howells extern void fscache_cookie_lookup_negative(struct fscache_cookie *cookie);
117d24af13eSDavid Howells extern void fscache_resume_after_invalidation(struct fscache_cookie *cookie);
1185d00e426SDavid Howells extern void fscache_caching_failed(struct fscache_cookie *cookie);
119d64f4554SDavid Howells extern bool fscache_wait_for_operation(struct netfs_cache_resources *cred,
120d64f4554SDavid Howells enum fscache_want_state state);
1215d00e426SDavid Howells
1225d00e426SDavid Howells /**
1235d00e426SDavid Howells * fscache_cookie_state - Read the state of a cookie
1245d00e426SDavid Howells * @cookie: The cookie to query
1255d00e426SDavid Howells *
1265d00e426SDavid Howells * Get the state of a cookie, imposing an ordering between the cookie contents
1275d00e426SDavid Howells * and the state value. Paired with fscache_set_cookie_state().
1285d00e426SDavid Howells */
1295d00e426SDavid Howells static inline
fscache_cookie_state(struct fscache_cookie * cookie)1305d00e426SDavid Howells enum fscache_cookie_state fscache_cookie_state(struct fscache_cookie *cookie)
1315d00e426SDavid Howells {
1325d00e426SDavid Howells return smp_load_acquire(&cookie->state);
1335d00e426SDavid Howells }
1347f3283abSDavid Howells
1357f3283abSDavid Howells /**
1367f3283abSDavid Howells * fscache_get_key - Get a pointer to the cookie key
1377f3283abSDavid Howells * @cookie: The cookie to query
1387f3283abSDavid Howells *
1397f3283abSDavid Howells * Return a pointer to the where a cookie's key is stored.
1407f3283abSDavid Howells */
fscache_get_key(struct fscache_cookie * cookie)1417f3283abSDavid Howells static inline void *fscache_get_key(struct fscache_cookie *cookie)
1427f3283abSDavid Howells {
1437f3283abSDavid Howells if (cookie->key_len <= sizeof(cookie->inline_key))
1447f3283abSDavid Howells return cookie->inline_key;
1457f3283abSDavid Howells else
1467f3283abSDavid Howells return cookie->key;
1477f3283abSDavid Howells }
1487f3283abSDavid Howells
fscache_cres_cookie(struct netfs_cache_resources * cres)149d64f4554SDavid Howells static inline struct fscache_cookie *fscache_cres_cookie(struct netfs_cache_resources *cres)
150d64f4554SDavid Howells {
151d64f4554SDavid Howells return cres->cache_priv;
152d64f4554SDavid Howells }
153d64f4554SDavid Howells
154cdf262f2SDavid Howells /**
155cdf262f2SDavid Howells * fscache_count_object - Tell fscache that an object has been added
156cdf262f2SDavid Howells * @cache: The cache to account to
157cdf262f2SDavid Howells *
158cdf262f2SDavid Howells * Tell fscache that an object has been added to the cache. This prevents the
159cdf262f2SDavid Howells * cache from tearing down the cache structure until the object is uncounted.
160cdf262f2SDavid Howells */
fscache_count_object(struct fscache_cache * cache)161cdf262f2SDavid Howells static inline void fscache_count_object(struct fscache_cache *cache)
162cdf262f2SDavid Howells {
163cdf262f2SDavid Howells atomic_inc(&cache->object_count);
164cdf262f2SDavid Howells }
165cdf262f2SDavid Howells
166cdf262f2SDavid Howells /**
167cdf262f2SDavid Howells * fscache_uncount_object - Tell fscache that an object has been removed
168cdf262f2SDavid Howells * @cache: The cache to account to
169cdf262f2SDavid Howells *
170cdf262f2SDavid Howells * Tell fscache that an object has been removed from the cache and will no
171cdf262f2SDavid Howells * longer be accessed. After this point, the cache cookie may be destroyed.
172cdf262f2SDavid Howells */
fscache_uncount_object(struct fscache_cache * cache)173cdf262f2SDavid Howells static inline void fscache_uncount_object(struct fscache_cache *cache)
174cdf262f2SDavid Howells {
175cdf262f2SDavid Howells if (atomic_dec_and_test(&cache->object_count))
176cdf262f2SDavid Howells wake_up_all(&fscache_clearance_waiters);
177cdf262f2SDavid Howells }
178cdf262f2SDavid Howells
179cdf262f2SDavid Howells /**
180cdf262f2SDavid Howells * fscache_wait_for_objects - Wait for all objects to be withdrawn
181cdf262f2SDavid Howells * @cache: The cache to query
182cdf262f2SDavid Howells *
183cdf262f2SDavid Howells * Wait for all extant objects in a cache to finish being withdrawn
184cdf262f2SDavid Howells * and go away.
185cdf262f2SDavid Howells */
fscache_wait_for_objects(struct fscache_cache * cache)186cdf262f2SDavid Howells static inline void fscache_wait_for_objects(struct fscache_cache *cache)
187cdf262f2SDavid Howells {
188cdf262f2SDavid Howells wait_event(fscache_clearance_waiters,
189cdf262f2SDavid Howells atomic_read(&cache->object_count) == 0);
190cdf262f2SDavid Howells }
191cdf262f2SDavid Howells
1928e7a867bSDavid Howells #ifdef CONFIG_FSCACHE_STATS
1938e7a867bSDavid Howells extern atomic_t fscache_n_read;
1948e7a867bSDavid Howells extern atomic_t fscache_n_write;
1953929eca7SDavid Howells extern atomic_t fscache_n_no_write_space;
1963929eca7SDavid Howells extern atomic_t fscache_n_no_create_space;
1979f08ebc3SDavid Howells extern atomic_t fscache_n_culled;
19892a714d7SDavid Howells extern atomic_t fscache_n_dio_misfit;
1998e7a867bSDavid Howells #define fscache_count_read() atomic_inc(&fscache_n_read)
2008e7a867bSDavid Howells #define fscache_count_write() atomic_inc(&fscache_n_write)
2013929eca7SDavid Howells #define fscache_count_no_write_space() atomic_inc(&fscache_n_no_write_space)
2023929eca7SDavid Howells #define fscache_count_no_create_space() atomic_inc(&fscache_n_no_create_space)
2039f08ebc3SDavid Howells #define fscache_count_culled() atomic_inc(&fscache_n_culled)
20492a714d7SDavid Howells #define fscache_count_dio_misfit() atomic_inc(&fscache_n_dio_misfit)
2058e7a867bSDavid Howells #else
2068e7a867bSDavid Howells #define fscache_count_read() do {} while(0)
2078e7a867bSDavid Howells #define fscache_count_write() do {} while(0)
2083929eca7SDavid Howells #define fscache_count_no_write_space() do {} while(0)
2093929eca7SDavid Howells #define fscache_count_no_create_space() do {} while(0)
2109f08ebc3SDavid Howells #define fscache_count_culled() do {} while(0)
21192a714d7SDavid Howells #define fscache_count_dio_misfit() do {} while(0)
2128e7a867bSDavid Howells #endif
2138e7a867bSDavid Howells
2140dfc41d1SDavid Howells #endif /* _LINUX_FSCACHE_CACHE_H */
215