1 /* FS-Cache interface to CacheFiles
2  *
3  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public Licence
8  * as published by the Free Software Foundation; either version
9  * 2 of the Licence, or (at your option) any later version.
10  */
11 
12 #include <linux/slab.h>
13 #include <linux/mount.h>
14 #include <linux/buffer_head.h>
15 #include "internal.h"
16 
17 #define list_to_page(head) (list_entry((head)->prev, struct page, lru))
18 
19 struct cachefiles_lookup_data {
20 	struct cachefiles_xattr	*auxdata;	/* auxiliary data */
21 	char			*key;		/* key path */
22 };
23 
24 static int cachefiles_attr_changed(struct fscache_object *_object);
25 
26 /*
27  * allocate an object record for a cookie lookup and prepare the lookup data
28  */
cachefiles_alloc_object(struct fscache_cache * _cache,struct fscache_cookie * cookie)29 static struct fscache_object *cachefiles_alloc_object(
30 	struct fscache_cache *_cache,
31 	struct fscache_cookie *cookie)
32 {
33 	struct cachefiles_lookup_data *lookup_data;
34 	struct cachefiles_object *object;
35 	struct cachefiles_cache *cache;
36 	struct cachefiles_xattr *auxdata;
37 	unsigned keylen, auxlen;
38 	void *buffer;
39 	char *key;
40 
41 	cache = container_of(_cache, struct cachefiles_cache, cache);
42 
43 	_enter("{%s},%p,", cache->cache.identifier, cookie);
44 
45 	lookup_data = kmalloc(sizeof(*lookup_data), GFP_KERNEL);
46 	if (!lookup_data)
47 		goto nomem_lookup_data;
48 
49 	/* create a new object record and a temporary leaf image */
50 	object = kmem_cache_alloc(cachefiles_object_jar, GFP_KERNEL);
51 	if (!object)
52 		goto nomem_object;
53 
54 	ASSERTCMP(object->backer, ==, NULL);
55 
56 	BUG_ON(test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags));
57 	atomic_set(&object->usage, 1);
58 
59 	fscache_object_init(&object->fscache, cookie, &cache->cache);
60 
61 	object->type = cookie->def->type;
62 
63 	/* get hold of the raw key
64 	 * - stick the length on the front and leave space on the back for the
65 	 *   encoder
66 	 */
67 	buffer = kmalloc((2 + 512) + 3, GFP_KERNEL);
68 	if (!buffer)
69 		goto nomem_buffer;
70 
71 	keylen = cookie->def->get_key(cookie->netfs_data, buffer + 2, 512);
72 	ASSERTCMP(keylen, <, 512);
73 
74 	*(uint16_t *)buffer = keylen;
75 	((char *)buffer)[keylen + 2] = 0;
76 	((char *)buffer)[keylen + 3] = 0;
77 	((char *)buffer)[keylen + 4] = 0;
78 
79 	/* turn the raw key into something that can work with as a filename */
80 	key = cachefiles_cook_key(buffer, keylen + 2, object->type);
81 	if (!key)
82 		goto nomem_key;
83 
84 	/* get hold of the auxiliary data and prepend the object type */
85 	auxdata = buffer;
86 	auxlen = 0;
87 	if (cookie->def->get_aux) {
88 		auxlen = cookie->def->get_aux(cookie->netfs_data,
89 					      auxdata->data, 511);
90 		ASSERTCMP(auxlen, <, 511);
91 	}
92 
93 	auxdata->len = auxlen + 1;
94 	auxdata->type = cookie->def->type;
95 
96 	lookup_data->auxdata = auxdata;
97 	lookup_data->key = key;
98 	object->lookup_data = lookup_data;
99 
100 	_leave(" = %p [%p]", &object->fscache, lookup_data);
101 	return &object->fscache;
102 
103 nomem_key:
104 	kfree(buffer);
105 nomem_buffer:
106 	BUG_ON(test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags));
107 	kmem_cache_free(cachefiles_object_jar, object);
108 	fscache_object_destroyed(&cache->cache);
109 nomem_object:
110 	kfree(lookup_data);
111 nomem_lookup_data:
112 	_leave(" = -ENOMEM");
113 	return ERR_PTR(-ENOMEM);
114 }
115 
116 /*
117  * attempt to look up the nominated node in this cache
118  * - return -ETIMEDOUT to be scheduled again
119  */
cachefiles_lookup_object(struct fscache_object * _object)120 static int cachefiles_lookup_object(struct fscache_object *_object)
121 {
122 	struct cachefiles_lookup_data *lookup_data;
123 	struct cachefiles_object *parent, *object;
124 	struct cachefiles_cache *cache;
125 	const struct cred *saved_cred;
126 	int ret;
127 
128 	_enter("{OBJ%x}", _object->debug_id);
129 
130 	cache = container_of(_object->cache, struct cachefiles_cache, cache);
131 	parent = container_of(_object->parent,
132 			      struct cachefiles_object, fscache);
133 	object = container_of(_object, struct cachefiles_object, fscache);
134 	lookup_data = object->lookup_data;
135 
136 	ASSERTCMP(lookup_data, !=, NULL);
137 
138 	/* look up the key, creating any missing bits */
139 	cachefiles_begin_secure(cache, &saved_cred);
140 	ret = cachefiles_walk_to_object(parent, object,
141 					lookup_data->key,
142 					lookup_data->auxdata);
143 	cachefiles_end_secure(cache, saved_cred);
144 
145 	/* polish off by setting the attributes of non-index files */
146 	if (ret == 0 &&
147 	    object->fscache.cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX)
148 		cachefiles_attr_changed(&object->fscache);
149 
150 	if (ret < 0 && ret != -ETIMEDOUT) {
151 		if (ret != -ENOBUFS)
152 			printk(KERN_WARNING
153 			       "CacheFiles: Lookup failed error %d\n", ret);
154 		fscache_object_lookup_error(&object->fscache);
155 	}
156 
157 	_leave(" [%d]", ret);
158 	return ret;
159 }
160 
161 /*
162  * indication of lookup completion
163  */
cachefiles_lookup_complete(struct fscache_object * _object)164 static void cachefiles_lookup_complete(struct fscache_object *_object)
165 {
166 	struct cachefiles_object *object;
167 
168 	object = container_of(_object, struct cachefiles_object, fscache);
169 
170 	_enter("{OBJ%x,%p}", object->fscache.debug_id, object->lookup_data);
171 
172 	if (object->lookup_data) {
173 		kfree(object->lookup_data->key);
174 		kfree(object->lookup_data->auxdata);
175 		kfree(object->lookup_data);
176 		object->lookup_data = NULL;
177 	}
178 }
179 
180 /*
181  * increment the usage count on an inode object (may fail if unmounting)
182  */
183 static
cachefiles_grab_object(struct fscache_object * _object)184 struct fscache_object *cachefiles_grab_object(struct fscache_object *_object)
185 {
186 	struct cachefiles_object *object =
187 		container_of(_object, struct cachefiles_object, fscache);
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 	atomic_inc(&object->usage);
196 	return &object->fscache;
197 }
198 
199 /*
200  * update the auxiliary data for an object object on disk
201  */
cachefiles_update_object(struct fscache_object * _object)202 static void cachefiles_update_object(struct fscache_object *_object)
203 {
204 	struct cachefiles_object *object;
205 	struct cachefiles_xattr *auxdata;
206 	struct cachefiles_cache *cache;
207 	struct fscache_cookie *cookie;
208 	const struct cred *saved_cred;
209 	unsigned auxlen;
210 
211 	_enter("{OBJ%x}", _object->debug_id);
212 
213 	object = container_of(_object, struct cachefiles_object, fscache);
214 	cache = container_of(object->fscache.cache, struct cachefiles_cache,
215 			     cache);
216 	cookie = object->fscache.cookie;
217 
218 	if (!cookie->def->get_aux) {
219 		_leave(" [no aux]");
220 		return;
221 	}
222 
223 	auxdata = kmalloc(2 + 512 + 3, GFP_KERNEL);
224 	if (!auxdata) {
225 		_leave(" [nomem]");
226 		return;
227 	}
228 
229 	auxlen = cookie->def->get_aux(cookie->netfs_data, auxdata->data, 511);
230 	ASSERTCMP(auxlen, <, 511);
231 
232 	auxdata->len = auxlen + 1;
233 	auxdata->type = cookie->def->type;
234 
235 	cachefiles_begin_secure(cache, &saved_cred);
236 	cachefiles_update_object_xattr(object, auxdata);
237 	cachefiles_end_secure(cache, saved_cred);
238 	kfree(auxdata);
239 	_leave("");
240 }
241 
242 /*
243  * discard the resources pinned by an object and effect retirement if
244  * requested
245  */
cachefiles_drop_object(struct fscache_object * _object)246 static void cachefiles_drop_object(struct fscache_object *_object)
247 {
248 	struct cachefiles_object *object;
249 	struct cachefiles_cache *cache;
250 	const struct cred *saved_cred;
251 
252 	ASSERT(_object);
253 
254 	object = container_of(_object, struct cachefiles_object, fscache);
255 
256 	_enter("{OBJ%x,%d}",
257 	       object->fscache.debug_id, atomic_read(&object->usage));
258 
259 	cache = container_of(object->fscache.cache,
260 			     struct cachefiles_cache, cache);
261 
262 #ifdef CACHEFILES_DEBUG_SLAB
263 	ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
264 #endif
265 
266 	/* delete retired objects */
267 	if (object->fscache.state == FSCACHE_OBJECT_RECYCLING &&
268 	    _object != cache->cache.fsdef
269 	    ) {
270 		_debug("- retire object OBJ%x", object->fscache.debug_id);
271 		cachefiles_begin_secure(cache, &saved_cred);
272 		cachefiles_delete_object(cache, object);
273 		cachefiles_end_secure(cache, saved_cred);
274 	}
275 
276 	/* close the filesystem stuff attached to the object */
277 	if (object->backer != object->dentry)
278 		dput(object->backer);
279 	object->backer = NULL;
280 
281 	/* note that the object is now inactive */
282 	if (test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)) {
283 		write_lock(&cache->active_lock);
284 		if (!test_and_clear_bit(CACHEFILES_OBJECT_ACTIVE,
285 					&object->flags))
286 			BUG();
287 		rb_erase(&object->active_node, &cache->active_nodes);
288 		wake_up_bit(&object->flags, CACHEFILES_OBJECT_ACTIVE);
289 		write_unlock(&cache->active_lock);
290 	}
291 
292 	dput(object->dentry);
293 	object->dentry = NULL;
294 
295 	_leave("");
296 }
297 
298 /*
299  * dispose of a reference to an object
300  */
cachefiles_put_object(struct fscache_object * _object)301 static void cachefiles_put_object(struct fscache_object *_object)
302 {
303 	struct cachefiles_object *object;
304 	struct fscache_cache *cache;
305 
306 	ASSERT(_object);
307 
308 	object = container_of(_object, struct cachefiles_object, fscache);
309 
310 	_enter("{OBJ%x,%d}",
311 	       object->fscache.debug_id, atomic_read(&object->usage));
312 
313 #ifdef CACHEFILES_DEBUG_SLAB
314 	ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
315 #endif
316 
317 	ASSERTIFCMP(object->fscache.parent,
318 		    object->fscache.parent->n_children, >, 0);
319 
320 	if (atomic_dec_and_test(&object->usage)) {
321 		_debug("- kill object OBJ%x", object->fscache.debug_id);
322 
323 		ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags));
324 		ASSERTCMP(object->fscache.parent, ==, NULL);
325 		ASSERTCMP(object->backer, ==, NULL);
326 		ASSERTCMP(object->dentry, ==, NULL);
327 		ASSERTCMP(object->fscache.n_ops, ==, 0);
328 		ASSERTCMP(object->fscache.n_children, ==, 0);
329 
330 		if (object->lookup_data) {
331 			kfree(object->lookup_data->key);
332 			kfree(object->lookup_data->auxdata);
333 			kfree(object->lookup_data);
334 			object->lookup_data = NULL;
335 		}
336 
337 		cache = object->fscache.cache;
338 		fscache_object_destroy(&object->fscache);
339 		kmem_cache_free(cachefiles_object_jar, object);
340 		fscache_object_destroyed(cache);
341 	}
342 
343 	_leave("");
344 }
345 
346 /*
347  * sync a cache
348  */
cachefiles_sync_cache(struct fscache_cache * _cache)349 static void cachefiles_sync_cache(struct fscache_cache *_cache)
350 {
351 	struct cachefiles_cache *cache;
352 	const struct cred *saved_cred;
353 	int ret;
354 
355 	_enter("%p", _cache);
356 
357 	cache = container_of(_cache, struct cachefiles_cache, cache);
358 
359 	/* make sure all pages pinned by operations on behalf of the netfs are
360 	 * written to disc */
361 	cachefiles_begin_secure(cache, &saved_cred);
362 	down_read(&cache->mnt->mnt_sb->s_umount);
363 	ret = sync_filesystem(cache->mnt->mnt_sb);
364 	up_read(&cache->mnt->mnt_sb->s_umount);
365 	cachefiles_end_secure(cache, saved_cred);
366 
367 	if (ret == -EIO)
368 		cachefiles_io_error(cache,
369 				    "Attempt to sync backing fs superblock"
370 				    " returned error %d",
371 				    ret);
372 }
373 
374 /*
375  * notification the attributes on an object have changed
376  * - called with reads/writes excluded by FS-Cache
377  */
cachefiles_attr_changed(struct fscache_object * _object)378 static int cachefiles_attr_changed(struct fscache_object *_object)
379 {
380 	struct cachefiles_object *object;
381 	struct cachefiles_cache *cache;
382 	const struct cred *saved_cred;
383 	struct iattr newattrs;
384 	uint64_t ni_size;
385 	loff_t oi_size;
386 	int ret;
387 
388 	_object->cookie->def->get_attr(_object->cookie->netfs_data, &ni_size);
389 
390 	_enter("{OBJ%x},[%llu]",
391 	       _object->debug_id, (unsigned long long) ni_size);
392 
393 	object = container_of(_object, struct cachefiles_object, fscache);
394 	cache = container_of(object->fscache.cache,
395 			     struct cachefiles_cache, cache);
396 
397 	if (ni_size == object->i_size)
398 		return 0;
399 
400 	if (!object->backer)
401 		return -ENOBUFS;
402 
403 	ASSERT(S_ISREG(object->backer->d_inode->i_mode));
404 
405 	fscache_set_store_limit(&object->fscache, ni_size);
406 
407 	oi_size = i_size_read(object->backer->d_inode);
408 	if (oi_size == ni_size)
409 		return 0;
410 
411 	cachefiles_begin_secure(cache, &saved_cred);
412 	mutex_lock(&object->backer->d_inode->i_mutex);
413 
414 	/* if there's an extension to a partial page at the end of the backing
415 	 * file, we need to discard the partial page so that we pick up new
416 	 * data after it */
417 	if (oi_size & ~PAGE_MASK && ni_size > oi_size) {
418 		_debug("discard tail %llx", oi_size);
419 		newattrs.ia_valid = ATTR_SIZE;
420 		newattrs.ia_size = oi_size & PAGE_MASK;
421 		ret = notify_change(object->backer, &newattrs);
422 		if (ret < 0)
423 			goto truncate_failed;
424 	}
425 
426 	newattrs.ia_valid = ATTR_SIZE;
427 	newattrs.ia_size = ni_size;
428 	ret = notify_change(object->backer, &newattrs);
429 
430 truncate_failed:
431 	mutex_unlock(&object->backer->d_inode->i_mutex);
432 	cachefiles_end_secure(cache, saved_cred);
433 
434 	if (ret == -EIO) {
435 		fscache_set_store_limit(&object->fscache, 0);
436 		cachefiles_io_error_obj(object, "Size set failed");
437 		ret = -ENOBUFS;
438 	}
439 
440 	_leave(" = %d", ret);
441 	return ret;
442 }
443 
444 /*
445  * dissociate a cache from all the pages it was backing
446  */
cachefiles_dissociate_pages(struct fscache_cache * cache)447 static void cachefiles_dissociate_pages(struct fscache_cache *cache)
448 {
449 	_enter("");
450 }
451 
452 const struct fscache_cache_ops cachefiles_cache_ops = {
453 	.name			= "cachefiles",
454 	.alloc_object		= cachefiles_alloc_object,
455 	.lookup_object		= cachefiles_lookup_object,
456 	.lookup_complete	= cachefiles_lookup_complete,
457 	.grab_object		= cachefiles_grab_object,
458 	.update_object		= cachefiles_update_object,
459 	.drop_object		= cachefiles_drop_object,
460 	.put_object		= cachefiles_put_object,
461 	.sync_cache		= cachefiles_sync_cache,
462 	.attr_changed		= cachefiles_attr_changed,
463 	.read_or_alloc_page	= cachefiles_read_or_alloc_page,
464 	.read_or_alloc_pages	= cachefiles_read_or_alloc_pages,
465 	.allocate_page		= cachefiles_allocate_page,
466 	.allocate_pages		= cachefiles_allocate_pages,
467 	.write_page		= cachefiles_write_page,
468 	.uncache_page		= cachefiles_uncache_page,
469 	.dissociate_pages	= cachefiles_dissociate_pages,
470 };
471