xref: /openbmc/linux/fs/cachefiles/interface.c (revision 423997ff)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* FS-Cache interface to CacheFiles
3  *
4  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  */
7 
8 #include <linux/slab.h>
9 #include <linux/mount.h>
10 #include "internal.h"
11 
12 struct cachefiles_lookup_data {
13 	struct cachefiles_xattr	*auxdata;	/* auxiliary data */
14 	char			*key;		/* key path */
15 };
16 
17 static int cachefiles_attr_changed(struct fscache_object *_object);
18 
19 /*
20  * allocate an object record for a cookie lookup and prepare the lookup data
21  */
22 static struct fscache_object *cachefiles_alloc_object(
23 	struct fscache_cache *_cache,
24 	struct fscache_cookie *cookie)
25 {
26 	struct cachefiles_lookup_data *lookup_data;
27 	struct cachefiles_object *object;
28 	struct cachefiles_cache *cache;
29 	struct cachefiles_xattr *auxdata;
30 	unsigned keylen, auxlen;
31 	void *buffer, *p;
32 	char *key;
33 
34 	cache = container_of(_cache, struct cachefiles_cache, cache);
35 
36 	_enter("{%s},%p,", cache->cache.identifier, cookie);
37 
38 	lookup_data = kmalloc(sizeof(*lookup_data), cachefiles_gfp);
39 	if (!lookup_data)
40 		goto nomem_lookup_data;
41 
42 	/* create a new object record and a temporary leaf image */
43 	object = kmem_cache_alloc(cachefiles_object_jar, cachefiles_gfp);
44 	if (!object)
45 		goto nomem_object;
46 
47 	ASSERTCMP(object->backer, ==, NULL);
48 
49 	BUG_ON(test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags));
50 	atomic_set(&object->usage, 1);
51 
52 	fscache_object_init(&object->fscache, cookie, &cache->cache);
53 
54 	object->type = cookie->def->type;
55 
56 	/* get hold of the raw key
57 	 * - stick the length on the front and leave space on the back for the
58 	 *   encoder
59 	 */
60 	buffer = kmalloc((2 + 512) + 3, cachefiles_gfp);
61 	if (!buffer)
62 		goto nomem_buffer;
63 
64 	keylen = cookie->key_len;
65 	if (keylen <= sizeof(cookie->inline_key))
66 		p = cookie->inline_key;
67 	else
68 		p = cookie->key;
69 	memcpy(buffer + 2, p, keylen);
70 
71 	*(uint16_t *)buffer = keylen;
72 	((char *)buffer)[keylen + 2] = 0;
73 	((char *)buffer)[keylen + 3] = 0;
74 	((char *)buffer)[keylen + 4] = 0;
75 
76 	/* turn the raw key into something that can work with as a filename */
77 	key = cachefiles_cook_key(buffer, keylen + 2, object->type);
78 	if (!key)
79 		goto nomem_key;
80 
81 	/* get hold of the auxiliary data and prepend the object type */
82 	auxdata = buffer;
83 	auxlen = cookie->aux_len;
84 	if (auxlen) {
85 		if (auxlen <= sizeof(cookie->inline_aux))
86 			p = cookie->inline_aux;
87 		else
88 			p = cookie->aux;
89 		memcpy(auxdata->data, p, auxlen);
90 	}
91 
92 	auxdata->len = auxlen + 1;
93 	auxdata->type = cookie->type;
94 
95 	lookup_data->auxdata = auxdata;
96 	lookup_data->key = key;
97 	object->lookup_data = lookup_data;
98 
99 	_leave(" = %p [%p]", &object->fscache, lookup_data);
100 	return &object->fscache;
101 
102 nomem_key:
103 	kfree(buffer);
104 nomem_buffer:
105 	BUG_ON(test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags));
106 	kmem_cache_free(cachefiles_object_jar, object);
107 	fscache_object_destroyed(&cache->cache);
108 nomem_object:
109 	kfree(lookup_data);
110 nomem_lookup_data:
111 	_leave(" = -ENOMEM");
112 	return ERR_PTR(-ENOMEM);
113 }
114 
115 /*
116  * attempt to look up the nominated node in this cache
117  * - return -ETIMEDOUT to be scheduled again
118  */
119 static int cachefiles_lookup_object(struct fscache_object *_object)
120 {
121 	struct cachefiles_lookup_data *lookup_data;
122 	struct cachefiles_object *parent, *object;
123 	struct cachefiles_cache *cache;
124 	const struct cred *saved_cred;
125 	int ret;
126 
127 	_enter("{OBJ%x}", _object->debug_id);
128 
129 	cache = container_of(_object->cache, struct cachefiles_cache, cache);
130 	parent = container_of(_object->parent,
131 			      struct cachefiles_object, fscache);
132 	object = container_of(_object, struct cachefiles_object, fscache);
133 	lookup_data = object->lookup_data;
134 
135 	ASSERTCMP(lookup_data, !=, NULL);
136 
137 	/* look up the key, creating any missing bits */
138 	cachefiles_begin_secure(cache, &saved_cred);
139 	ret = cachefiles_walk_to_object(parent, object,
140 					lookup_data->key,
141 					lookup_data->auxdata);
142 	cachefiles_end_secure(cache, saved_cred);
143 
144 	/* polish off by setting the attributes of non-index files */
145 	if (ret == 0 &&
146 	    object->fscache.cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX)
147 		cachefiles_attr_changed(&object->fscache);
148 
149 	if (ret < 0 && ret != -ETIMEDOUT) {
150 		if (ret != -ENOBUFS)
151 			pr_warn("Lookup failed error %d\n", ret);
152 		fscache_object_lookup_error(&object->fscache);
153 	}
154 
155 	_leave(" [%d]", ret);
156 	return ret;
157 }
158 
159 /*
160  * indication of lookup completion
161  */
162 static void cachefiles_lookup_complete(struct fscache_object *_object)
163 {
164 	struct cachefiles_object *object;
165 
166 	object = container_of(_object, struct cachefiles_object, fscache);
167 
168 	_enter("{OBJ%x,%p}", object->fscache.debug_id, object->lookup_data);
169 
170 	if (object->lookup_data) {
171 		kfree(object->lookup_data->key);
172 		kfree(object->lookup_data->auxdata);
173 		kfree(object->lookup_data);
174 		object->lookup_data = NULL;
175 	}
176 }
177 
178 /*
179  * increment the usage count on an inode object (may fail if unmounting)
180  */
181 static
182 struct fscache_object *cachefiles_grab_object(struct fscache_object *_object,
183 					      enum fscache_obj_ref_trace why)
184 {
185 	struct cachefiles_object *object =
186 		container_of(_object, struct cachefiles_object, fscache);
187 	int u;
188 
189 	_enter("{OBJ%x,%d}", _object->debug_id, atomic_read(&object->usage));
190 
191 #ifdef CACHEFILES_DEBUG_SLAB
192 	ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
193 #endif
194 
195 	u = atomic_inc_return(&object->usage);
196 	trace_cachefiles_ref(object, _object->cookie,
197 			     (enum cachefiles_obj_ref_trace)why, u);
198 	return &object->fscache;
199 }
200 
201 /*
202  * update the auxiliary data for an object object on disk
203  */
204 static void cachefiles_update_object(struct fscache_object *_object)
205 {
206 	struct cachefiles_object *object;
207 	struct cachefiles_xattr *auxdata;
208 	struct cachefiles_cache *cache;
209 	struct fscache_cookie *cookie;
210 	const struct cred *saved_cred;
211 	const void *aux;
212 	unsigned auxlen;
213 
214 	_enter("{OBJ%x}", _object->debug_id);
215 
216 	object = container_of(_object, struct cachefiles_object, fscache);
217 	cache = container_of(object->fscache.cache, struct cachefiles_cache,
218 			     cache);
219 
220 	if (!fscache_use_cookie(_object)) {
221 		_leave(" [relinq]");
222 		return;
223 	}
224 
225 	cookie = object->fscache.cookie;
226 	auxlen = cookie->aux_len;
227 
228 	if (!auxlen) {
229 		fscache_unuse_cookie(_object);
230 		_leave(" [no aux]");
231 		return;
232 	}
233 
234 	auxdata = kmalloc(2 + auxlen + 3, cachefiles_gfp);
235 	if (!auxdata) {
236 		fscache_unuse_cookie(_object);
237 		_leave(" [nomem]");
238 		return;
239 	}
240 
241 	aux = (auxlen <= sizeof(cookie->inline_aux)) ?
242 		cookie->inline_aux : cookie->aux;
243 
244 	memcpy(auxdata->data, aux, auxlen);
245 	fscache_unuse_cookie(_object);
246 
247 	auxdata->len = auxlen + 1;
248 	auxdata->type = cookie->type;
249 
250 	cachefiles_begin_secure(cache, &saved_cred);
251 	cachefiles_update_object_xattr(object, auxdata);
252 	cachefiles_end_secure(cache, saved_cred);
253 	kfree(auxdata);
254 	_leave("");
255 }
256 
257 /*
258  * discard the resources pinned by an object and effect retirement if
259  * requested
260  */
261 static void cachefiles_drop_object(struct fscache_object *_object)
262 {
263 	struct cachefiles_object *object;
264 	struct cachefiles_cache *cache;
265 	const struct cred *saved_cred;
266 	struct inode *inode;
267 	blkcnt_t i_blocks = 0;
268 
269 	ASSERT(_object);
270 
271 	object = container_of(_object, struct cachefiles_object, fscache);
272 
273 	_enter("{OBJ%x,%d}",
274 	       object->fscache.debug_id, atomic_read(&object->usage));
275 
276 	cache = container_of(object->fscache.cache,
277 			     struct cachefiles_cache, cache);
278 
279 #ifdef CACHEFILES_DEBUG_SLAB
280 	ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
281 #endif
282 
283 	/* We need to tidy the object up if we did in fact manage to open it.
284 	 * It's possible for us to get here before the object is fully
285 	 * initialised if the parent goes away or the object gets retired
286 	 * before we set it up.
287 	 */
288 	if (object->dentry) {
289 		/* delete retired objects */
290 		if (test_bit(FSCACHE_OBJECT_RETIRED, &object->fscache.flags) &&
291 		    _object != cache->cache.fsdef
292 		    ) {
293 			_debug("- retire object OBJ%x", object->fscache.debug_id);
294 			inode = d_backing_inode(object->dentry);
295 			if (inode)
296 				i_blocks = inode->i_blocks;
297 
298 			cachefiles_begin_secure(cache, &saved_cred);
299 			cachefiles_delete_object(cache, object);
300 			cachefiles_end_secure(cache, saved_cred);
301 		}
302 
303 		/* close the filesystem stuff attached to the object */
304 		if (object->backer != object->dentry)
305 			dput(object->backer);
306 		object->backer = NULL;
307 	}
308 
309 	/* note that the object is now inactive */
310 	if (test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags))
311 		cachefiles_mark_object_inactive(cache, object, i_blocks);
312 
313 	dput(object->dentry);
314 	object->dentry = NULL;
315 
316 	_leave("");
317 }
318 
319 /*
320  * dispose of a reference to an object
321  */
322 static void cachefiles_put_object(struct fscache_object *_object,
323 				  enum fscache_obj_ref_trace why)
324 {
325 	struct cachefiles_object *object;
326 	struct fscache_cache *cache;
327 	int u;
328 
329 	ASSERT(_object);
330 
331 	object = container_of(_object, struct cachefiles_object, fscache);
332 
333 	_enter("{OBJ%x,%d}",
334 	       object->fscache.debug_id, atomic_read(&object->usage));
335 
336 #ifdef CACHEFILES_DEBUG_SLAB
337 	ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
338 #endif
339 
340 	ASSERTIFCMP(object->fscache.parent,
341 		    object->fscache.parent->n_children, >, 0);
342 
343 	u = atomic_dec_return(&object->usage);
344 	trace_cachefiles_ref(object, _object->cookie,
345 			     (enum cachefiles_obj_ref_trace)why, u);
346 	ASSERTCMP(u, !=, -1);
347 	if (u == 0) {
348 		_debug("- kill object OBJ%x", object->fscache.debug_id);
349 
350 		ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags));
351 		ASSERTCMP(object->fscache.parent, ==, NULL);
352 		ASSERTCMP(object->backer, ==, NULL);
353 		ASSERTCMP(object->dentry, ==, NULL);
354 		ASSERTCMP(object->fscache.n_ops, ==, 0);
355 		ASSERTCMP(object->fscache.n_children, ==, 0);
356 
357 		if (object->lookup_data) {
358 			kfree(object->lookup_data->key);
359 			kfree(object->lookup_data->auxdata);
360 			kfree(object->lookup_data);
361 			object->lookup_data = NULL;
362 		}
363 
364 		cache = object->fscache.cache;
365 		fscache_object_destroy(&object->fscache);
366 		kmem_cache_free(cachefiles_object_jar, object);
367 		fscache_object_destroyed(cache);
368 	}
369 
370 	_leave("");
371 }
372 
373 /*
374  * sync a cache
375  */
376 static void cachefiles_sync_cache(struct fscache_cache *_cache)
377 {
378 	struct cachefiles_cache *cache;
379 	const struct cred *saved_cred;
380 	int ret;
381 
382 	_enter("%p", _cache);
383 
384 	cache = container_of(_cache, struct cachefiles_cache, cache);
385 
386 	/* make sure all pages pinned by operations on behalf of the netfs are
387 	 * written to disc */
388 	cachefiles_begin_secure(cache, &saved_cred);
389 	down_read(&cache->mnt->mnt_sb->s_umount);
390 	ret = sync_filesystem(cache->mnt->mnt_sb);
391 	up_read(&cache->mnt->mnt_sb->s_umount);
392 	cachefiles_end_secure(cache, saved_cred);
393 
394 	if (ret == -EIO)
395 		cachefiles_io_error(cache,
396 				    "Attempt to sync backing fs superblock"
397 				    " returned error %d",
398 				    ret);
399 }
400 
401 /*
402  * check if the backing cache is updated to FS-Cache
403  * - called by FS-Cache when evaluates if need to invalidate the cache
404  */
405 static int cachefiles_check_consistency(struct fscache_operation *op)
406 {
407 	struct cachefiles_object *object;
408 	struct cachefiles_cache *cache;
409 	const struct cred *saved_cred;
410 	int ret;
411 
412 	_enter("{OBJ%x}", op->object->debug_id);
413 
414 	object = container_of(op->object, struct cachefiles_object, fscache);
415 	cache = container_of(object->fscache.cache,
416 			     struct cachefiles_cache, cache);
417 
418 	cachefiles_begin_secure(cache, &saved_cred);
419 	ret = cachefiles_check_auxdata(object);
420 	cachefiles_end_secure(cache, saved_cred);
421 
422 	_leave(" = %d", ret);
423 	return ret;
424 }
425 
426 /*
427  * notification the attributes on an object have changed
428  * - called with reads/writes excluded by FS-Cache
429  */
430 static int cachefiles_attr_changed(struct fscache_object *_object)
431 {
432 	struct cachefiles_object *object;
433 	struct cachefiles_cache *cache;
434 	const struct cred *saved_cred;
435 	struct iattr newattrs;
436 	uint64_t ni_size;
437 	loff_t oi_size;
438 	int ret;
439 
440 	ni_size = _object->store_limit_l;
441 
442 	_enter("{OBJ%x},[%llu]",
443 	       _object->debug_id, (unsigned long long) ni_size);
444 
445 	object = container_of(_object, struct cachefiles_object, fscache);
446 	cache = container_of(object->fscache.cache,
447 			     struct cachefiles_cache, cache);
448 
449 	if (ni_size == object->i_size)
450 		return 0;
451 
452 	if (!object->backer)
453 		return -ENOBUFS;
454 
455 	ASSERT(d_is_reg(object->backer));
456 
457 	fscache_set_store_limit(&object->fscache, ni_size);
458 
459 	oi_size = i_size_read(d_backing_inode(object->backer));
460 	if (oi_size == ni_size)
461 		return 0;
462 
463 	cachefiles_begin_secure(cache, &saved_cred);
464 	inode_lock(d_inode(object->backer));
465 
466 	/* if there's an extension to a partial page at the end of the backing
467 	 * file, we need to discard the partial page so that we pick up new
468 	 * data after it */
469 	if (oi_size & ~PAGE_MASK && ni_size > oi_size) {
470 		_debug("discard tail %llx", oi_size);
471 		newattrs.ia_valid = ATTR_SIZE;
472 		newattrs.ia_size = oi_size & PAGE_MASK;
473 		ret = notify_change(object->backer, &newattrs, NULL);
474 		if (ret < 0)
475 			goto truncate_failed;
476 	}
477 
478 	newattrs.ia_valid = ATTR_SIZE;
479 	newattrs.ia_size = ni_size;
480 	ret = notify_change(object->backer, &newattrs, NULL);
481 
482 truncate_failed:
483 	inode_unlock(d_inode(object->backer));
484 	cachefiles_end_secure(cache, saved_cred);
485 
486 	if (ret == -EIO) {
487 		fscache_set_store_limit(&object->fscache, 0);
488 		cachefiles_io_error_obj(object, "Size set failed");
489 		ret = -ENOBUFS;
490 	}
491 
492 	_leave(" = %d", ret);
493 	return ret;
494 }
495 
496 /*
497  * Invalidate an object
498  */
499 static void cachefiles_invalidate_object(struct fscache_operation *op)
500 {
501 	struct cachefiles_object *object;
502 	struct cachefiles_cache *cache;
503 	const struct cred *saved_cred;
504 	struct path path;
505 	uint64_t ni_size;
506 	int ret;
507 
508 	object = container_of(op->object, struct cachefiles_object, fscache);
509 	cache = container_of(object->fscache.cache,
510 			     struct cachefiles_cache, cache);
511 
512 	ni_size = op->object->store_limit_l;
513 
514 	_enter("{OBJ%x},[%llu]",
515 	       op->object->debug_id, (unsigned long long)ni_size);
516 
517 	if (object->backer) {
518 		ASSERT(d_is_reg(object->backer));
519 
520 		fscache_set_store_limit(&object->fscache, ni_size);
521 
522 		path.dentry = object->backer;
523 		path.mnt = cache->mnt;
524 
525 		cachefiles_begin_secure(cache, &saved_cred);
526 		ret = vfs_truncate(&path, 0);
527 		if (ret == 0)
528 			ret = vfs_truncate(&path, ni_size);
529 		cachefiles_end_secure(cache, saved_cred);
530 
531 		if (ret != 0) {
532 			fscache_set_store_limit(&object->fscache, 0);
533 			if (ret == -EIO)
534 				cachefiles_io_error_obj(object,
535 							"Invalidate failed");
536 		}
537 	}
538 
539 	fscache_op_complete(op, true);
540 	_leave("");
541 }
542 
543 /*
544  * dissociate a cache from all the pages it was backing
545  */
546 static void cachefiles_dissociate_pages(struct fscache_cache *cache)
547 {
548 	_enter("");
549 }
550 
551 const struct fscache_cache_ops cachefiles_cache_ops = {
552 	.name			= "cachefiles",
553 	.alloc_object		= cachefiles_alloc_object,
554 	.lookup_object		= cachefiles_lookup_object,
555 	.lookup_complete	= cachefiles_lookup_complete,
556 	.grab_object		= cachefiles_grab_object,
557 	.update_object		= cachefiles_update_object,
558 	.invalidate_object	= cachefiles_invalidate_object,
559 	.drop_object		= cachefiles_drop_object,
560 	.put_object		= cachefiles_put_object,
561 	.sync_cache		= cachefiles_sync_cache,
562 	.attr_changed		= cachefiles_attr_changed,
563 	.read_or_alloc_page	= cachefiles_read_or_alloc_page,
564 	.read_or_alloc_pages	= cachefiles_read_or_alloc_pages,
565 	.allocate_page		= cachefiles_allocate_page,
566 	.allocate_pages		= cachefiles_allocate_pages,
567 	.write_page		= cachefiles_write_page,
568 	.uncache_page		= cachefiles_uncache_page,
569 	.dissociate_pages	= cachefiles_dissociate_pages,
570 	.check_consistency	= cachefiles_check_consistency,
571 };
572