xref: /openbmc/linux/fs/fscache/cache.c (revision fadbafc1)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* FS-Cache cache handling
3  *
4  * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  */
7 
8 #define FSCACHE_DEBUG_LEVEL CACHE
9 #include <linux/export.h>
10 #include <linux/slab.h>
11 #include "internal.h"
12 
13 static LIST_HEAD(fscache_caches);
14 DECLARE_RWSEM(fscache_addremove_sem);
15 EXPORT_SYMBOL(fscache_addremove_sem);
16 DECLARE_WAIT_QUEUE_HEAD(fscache_clearance_waiters);
17 EXPORT_SYMBOL(fscache_clearance_waiters);
18 
19 static atomic_t fscache_cache_debug_id;
20 
21 /*
22  * Allocate a cache cookie.
23  */
24 static struct fscache_cache *fscache_alloc_cache(const char *name)
25 {
26 	struct fscache_cache *cache;
27 
28 	cache = kzalloc(sizeof(*cache), GFP_KERNEL);
29 	if (cache) {
30 		if (name) {
31 			cache->name = kstrdup(name, GFP_KERNEL);
32 			if (!cache->name) {
33 				kfree(cache);
34 				return NULL;
35 			}
36 		}
37 		refcount_set(&cache->ref, 1);
38 		INIT_LIST_HEAD(&cache->cache_link);
39 		cache->debug_id = atomic_inc_return(&fscache_cache_debug_id);
40 	}
41 	return cache;
42 }
43 
44 static bool fscache_get_cache_maybe(struct fscache_cache *cache,
45 				    enum fscache_cache_trace where)
46 {
47 	bool success;
48 	int ref;
49 
50 	success = __refcount_inc_not_zero(&cache->ref, &ref);
51 	if (success)
52 		trace_fscache_cache(cache->debug_id, ref + 1, where);
53 	return success;
54 }
55 
56 /*
57  * Look up a cache cookie.
58  */
59 struct fscache_cache *fscache_lookup_cache(const char *name, bool is_cache)
60 {
61 	struct fscache_cache *candidate, *cache, *unnamed = NULL;
62 
63 	/* firstly check for the existence of the cache under read lock */
64 	down_read(&fscache_addremove_sem);
65 
66 	list_for_each_entry(cache, &fscache_caches, cache_link) {
67 		if (cache->name && name && strcmp(cache->name, name) == 0 &&
68 		    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
69 			goto got_cache_r;
70 		if (!cache->name && !name &&
71 		    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
72 			goto got_cache_r;
73 	}
74 
75 	if (!name) {
76 		list_for_each_entry(cache, &fscache_caches, cache_link) {
77 			if (cache->name &&
78 			    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
79 				goto got_cache_r;
80 		}
81 	}
82 
83 	up_read(&fscache_addremove_sem);
84 
85 	/* the cache does not exist - create a candidate */
86 	candidate = fscache_alloc_cache(name);
87 	if (!candidate)
88 		return ERR_PTR(-ENOMEM);
89 
90 	/* write lock, search again and add if still not present */
91 	down_write(&fscache_addremove_sem);
92 
93 	list_for_each_entry(cache, &fscache_caches, cache_link) {
94 		if (cache->name && name && strcmp(cache->name, name) == 0 &&
95 		    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
96 			goto got_cache_w;
97 		if (!cache->name) {
98 			unnamed = cache;
99 			if (!name &&
100 			    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
101 				goto got_cache_w;
102 		}
103 	}
104 
105 	if (unnamed && is_cache &&
106 	    fscache_get_cache_maybe(unnamed, fscache_cache_get_acquire))
107 		goto use_unnamed_cache;
108 
109 	if (!name) {
110 		list_for_each_entry(cache, &fscache_caches, cache_link) {
111 			if (cache->name &&
112 			    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
113 				goto got_cache_w;
114 		}
115 	}
116 
117 	list_add_tail(&candidate->cache_link, &fscache_caches);
118 	trace_fscache_cache(candidate->debug_id,
119 			    refcount_read(&candidate->ref),
120 			    fscache_cache_new_acquire);
121 	up_write(&fscache_addremove_sem);
122 	return candidate;
123 
124 got_cache_r:
125 	up_read(&fscache_addremove_sem);
126 	return cache;
127 use_unnamed_cache:
128 	cache = unnamed;
129 	cache->name = candidate->name;
130 	candidate->name = NULL;
131 got_cache_w:
132 	up_write(&fscache_addremove_sem);
133 	kfree(candidate->name);
134 	kfree(candidate);
135 	return cache;
136 }
137 
138 /**
139  * fscache_acquire_cache - Acquire a cache-level cookie.
140  * @name: The name of the cache.
141  *
142  * Get a cookie to represent an actual cache.  If a name is given and there is
143  * a nameless cache record available, this will acquire that and set its name,
144  * directing all the volumes using it to this cache.
145  *
146  * The cache will be switched over to the preparing state if not currently in
147  * use, otherwise -EBUSY will be returned.
148  */
149 struct fscache_cache *fscache_acquire_cache(const char *name)
150 {
151 	struct fscache_cache *cache;
152 
153 	ASSERT(name);
154 	cache = fscache_lookup_cache(name, true);
155 	if (IS_ERR(cache))
156 		return cache;
157 
158 	if (!fscache_set_cache_state_maybe(cache,
159 					   FSCACHE_CACHE_IS_NOT_PRESENT,
160 					   FSCACHE_CACHE_IS_PREPARING)) {
161 		pr_warn("Cache tag %s in use\n", name);
162 		fscache_put_cache(cache, fscache_cache_put_cache);
163 		return ERR_PTR(-EBUSY);
164 	}
165 
166 	return cache;
167 }
168 EXPORT_SYMBOL(fscache_acquire_cache);
169 
170 /**
171  * fscache_put_cache - Release a cache-level cookie.
172  * @cache: The cache cookie to be released
173  * @where: An indication of where the release happened
174  *
175  * Release the caller's reference on a cache-level cookie.  The @where
176  * indication should give information about the circumstances in which the call
177  * occurs and will be logged through a tracepoint.
178  */
179 void fscache_put_cache(struct fscache_cache *cache,
180 		       enum fscache_cache_trace where)
181 {
182 	unsigned int debug_id = cache->debug_id;
183 	bool zero;
184 	int ref;
185 
186 	if (IS_ERR_OR_NULL(cache))
187 		return;
188 
189 	zero = __refcount_dec_and_test(&cache->ref, &ref);
190 	trace_fscache_cache(debug_id, ref - 1, where);
191 
192 	if (zero) {
193 		down_write(&fscache_addremove_sem);
194 		list_del_init(&cache->cache_link);
195 		up_write(&fscache_addremove_sem);
196 		kfree(cache->name);
197 		kfree(cache);
198 	}
199 }
200 
201 /**
202  * fscache_relinquish_cache - Reset cache state and release cookie
203  * @cache: The cache cookie to be released
204  *
205  * Reset the state of a cache and release the caller's reference on a cache
206  * cookie.
207  */
208 void fscache_relinquish_cache(struct fscache_cache *cache)
209 {
210 	enum fscache_cache_trace where =
211 		(cache->state == FSCACHE_CACHE_IS_PREPARING) ?
212 		fscache_cache_put_prep_failed :
213 		fscache_cache_put_relinquish;
214 
215 	cache->ops = NULL;
216 	cache->cache_priv = NULL;
217 	fscache_set_cache_state(cache, FSCACHE_CACHE_IS_NOT_PRESENT);
218 	fscache_put_cache(cache, where);
219 }
220 EXPORT_SYMBOL(fscache_relinquish_cache);
221 
222 /**
223  * fscache_add_cache - Declare a cache as being open for business
224  * @cache: The cache-level cookie representing the cache
225  * @ops: Table of cache operations to use
226  * @cache_priv: Private data for the cache record
227  *
228  * Add a cache to the system, making it available for netfs's to use.
229  *
230  * See Documentation/filesystems/caching/backend-api.rst for a complete
231  * description.
232  */
233 int fscache_add_cache(struct fscache_cache *cache,
234 		      const struct fscache_cache_ops *ops,
235 		      void *cache_priv)
236 {
237 	int n_accesses;
238 
239 	_enter("{%s,%s}", ops->name, cache->name);
240 
241 	BUG_ON(fscache_cache_state(cache) != FSCACHE_CACHE_IS_PREPARING);
242 
243 	/* Get a ref on the cache cookie and keep its n_accesses counter raised
244 	 * by 1 to prevent wakeups from transitioning it to 0 until we're
245 	 * withdrawing caching services from it.
246 	 */
247 	n_accesses = atomic_inc_return(&cache->n_accesses);
248 	trace_fscache_access_cache(cache->debug_id, refcount_read(&cache->ref),
249 				   n_accesses, fscache_access_cache_pin);
250 
251 	down_write(&fscache_addremove_sem);
252 
253 	cache->ops = ops;
254 	cache->cache_priv = cache_priv;
255 	fscache_set_cache_state(cache, FSCACHE_CACHE_IS_ACTIVE);
256 
257 	up_write(&fscache_addremove_sem);
258 	pr_notice("Cache \"%s\" added (type %s)\n", cache->name, ops->name);
259 	_leave(" = 0 [%s]", cache->name);
260 	return 0;
261 }
262 EXPORT_SYMBOL(fscache_add_cache);
263 
264 /**
265  * fscache_begin_cache_access - Pin a cache so it can be accessed
266  * @cache: The cache-level cookie
267  * @why: An indication of the circumstances of the access for tracing
268  *
269  * Attempt to pin the cache to prevent it from going away whilst we're
270  * accessing it and returns true if successful.  This works as follows:
271  *
272  *  (1) If the cache tests as not live (state is not FSCACHE_CACHE_IS_ACTIVE),
273  *      then we return false to indicate access was not permitted.
274  *
275  *  (2) If the cache tests as live, then we increment the n_accesses count and
276  *      then recheck the liveness, ending the access if it ceased to be live.
277  *
278  *  (3) When we end the access, we decrement n_accesses and wake up the any
279  *      waiters if it reaches 0.
280  *
281  *  (4) Whilst the cache is caching, n_accesses is kept artificially
282  *      incremented to prevent wakeups from happening.
283  *
284  *  (5) When the cache is taken offline, the state is changed to prevent new
285  *      accesses, n_accesses is decremented and we wait for n_accesses to
286  *      become 0.
287  */
288 bool fscache_begin_cache_access(struct fscache_cache *cache, enum fscache_access_trace why)
289 {
290 	int n_accesses;
291 
292 	if (!fscache_cache_is_live(cache))
293 		return false;
294 
295 	n_accesses = atomic_inc_return(&cache->n_accesses);
296 	smp_mb__after_atomic(); /* Reread live flag after n_accesses */
297 	trace_fscache_access_cache(cache->debug_id, refcount_read(&cache->ref),
298 				   n_accesses, why);
299 	if (!fscache_cache_is_live(cache)) {
300 		fscache_end_cache_access(cache, fscache_access_unlive);
301 		return false;
302 	}
303 	return true;
304 }
305 
306 /**
307  * fscache_end_cache_access - Unpin a cache at the end of an access.
308  * @cache: The cache-level cookie
309  * @why: An indication of the circumstances of the access for tracing
310  *
311  * Unpin a cache after we've accessed it.  The @why indicator is merely
312  * provided for tracing purposes.
313  */
314 void fscache_end_cache_access(struct fscache_cache *cache, enum fscache_access_trace why)
315 {
316 	int n_accesses;
317 
318 	smp_mb__before_atomic();
319 	n_accesses = atomic_dec_return(&cache->n_accesses);
320 	trace_fscache_access_cache(cache->debug_id, refcount_read(&cache->ref),
321 				   n_accesses, why);
322 	if (n_accesses == 0)
323 		wake_up_var(&cache->n_accesses);
324 }
325 
326 /**
327  * fscache_io_error - Note a cache I/O error
328  * @cache: The record describing the cache
329  *
330  * Note that an I/O error occurred in a cache and that it should no longer be
331  * used for anything.  This also reports the error into the kernel log.
332  *
333  * See Documentation/filesystems/caching/backend-api.rst for a complete
334  * description.
335  */
336 void fscache_io_error(struct fscache_cache *cache)
337 {
338 	if (fscache_set_cache_state_maybe(cache,
339 					  FSCACHE_CACHE_IS_ACTIVE,
340 					  FSCACHE_CACHE_GOT_IOERROR))
341 		pr_err("Cache '%s' stopped due to I/O error\n",
342 		       cache->name);
343 }
344 EXPORT_SYMBOL(fscache_io_error);
345 
346 /**
347  * fscache_withdraw_cache - Withdraw a cache from the active service
348  * @cache: The cache cookie
349  *
350  * Begin the process of withdrawing a cache from service.  This stops new
351  * cache-level and volume-level accesses from taking place and waits for
352  * currently ongoing cache-level accesses to end.
353  */
354 void fscache_withdraw_cache(struct fscache_cache *cache)
355 {
356 	int n_accesses;
357 
358 	pr_notice("Withdrawing cache \"%s\" (%u objs)\n",
359 		  cache->name, atomic_read(&cache->object_count));
360 
361 	fscache_set_cache_state(cache, FSCACHE_CACHE_IS_WITHDRAWN);
362 
363 	/* Allow wakeups on dec-to-0 */
364 	n_accesses = atomic_dec_return(&cache->n_accesses);
365 	trace_fscache_access_cache(cache->debug_id, refcount_read(&cache->ref),
366 				   n_accesses, fscache_access_cache_unpin);
367 
368 	wait_var_event(&cache->n_accesses,
369 		       atomic_read(&cache->n_accesses) == 0);
370 }
371 EXPORT_SYMBOL(fscache_withdraw_cache);
372 
373 #ifdef CONFIG_PROC_FS
374 static const char fscache_cache_states[NR__FSCACHE_CACHE_STATE] = "-PAEW";
375 
376 /*
377  * Generate a list of caches in /proc/fs/fscache/caches
378  */
379 static int fscache_caches_seq_show(struct seq_file *m, void *v)
380 {
381 	struct fscache_cache *cache;
382 
383 	if (v == &fscache_caches) {
384 		seq_puts(m,
385 			 "CACHE    REF   VOLS  OBJS  ACCES S NAME\n"
386 			 "======== ===== ===== ===== ===== = ===============\n"
387 			 );
388 		return 0;
389 	}
390 
391 	cache = list_entry(v, struct fscache_cache, cache_link);
392 	seq_printf(m,
393 		   "%08x %5d %5d %5d %5d %c %s\n",
394 		   cache->debug_id,
395 		   refcount_read(&cache->ref),
396 		   atomic_read(&cache->n_volumes),
397 		   atomic_read(&cache->object_count),
398 		   atomic_read(&cache->n_accesses),
399 		   fscache_cache_states[cache->state],
400 		   cache->name ?: "-");
401 	return 0;
402 }
403 
404 static void *fscache_caches_seq_start(struct seq_file *m, loff_t *_pos)
405 	__acquires(fscache_addremove_sem)
406 {
407 	down_read(&fscache_addremove_sem);
408 	return seq_list_start_head(&fscache_caches, *_pos);
409 }
410 
411 static void *fscache_caches_seq_next(struct seq_file *m, void *v, loff_t *_pos)
412 {
413 	return seq_list_next(v, &fscache_caches, _pos);
414 }
415 
416 static void fscache_caches_seq_stop(struct seq_file *m, void *v)
417 	__releases(fscache_addremove_sem)
418 {
419 	up_read(&fscache_addremove_sem);
420 }
421 
422 const struct seq_operations fscache_caches_seq_ops = {
423 	.start  = fscache_caches_seq_start,
424 	.next   = fscache_caches_seq_next,
425 	.stop   = fscache_caches_seq_stop,
426 	.show   = fscache_caches_seq_show,
427 };
428 #endif /* CONFIG_PROC_FS */
429