Blame view

fs/cachefiles/interface.c 14.9 KB
b4d0d230c   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
9ae326a69   David Howells   CacheFiles: A cac...
2
3
4
5
  /* FS-Cache interface to CacheFiles
   *
   * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   * Written by David Howells (dhowells@redhat.com)
9ae326a69   David Howells   CacheFiles: A cac...
6
   */
5a0e3ad6a   Tejun Heo   include cleanup: ...
7
  #include <linux/slab.h>
9ae326a69   David Howells   CacheFiles: A cac...
8
  #include <linux/mount.h>
9ae326a69   David Howells   CacheFiles: A cac...
9
  #include "internal.h"
9ae326a69   David Howells   CacheFiles: A cac...
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  struct cachefiles_lookup_data {
  	struct cachefiles_xattr	*auxdata;	/* auxiliary data */
  	char			*key;		/* key path */
  };
  
  static int cachefiles_attr_changed(struct fscache_object *_object);
  
  /*
   * allocate an object record for a cookie lookup and prepare the lookup data
   */
  static struct fscache_object *cachefiles_alloc_object(
  	struct fscache_cache *_cache,
  	struct fscache_cookie *cookie)
  {
  	struct cachefiles_lookup_data *lookup_data;
  	struct cachefiles_object *object;
  	struct cachefiles_cache *cache;
  	struct cachefiles_xattr *auxdata;
  	unsigned keylen, auxlen;
402cb8dda   David Howells   fscache: Attach t...
29
  	void *buffer, *p;
9ae326a69   David Howells   CacheFiles: A cac...
30
31
32
33
34
  	char *key;
  
  	cache = container_of(_cache, struct cachefiles_cache, cache);
  
  	_enter("{%s},%p,", cache->cache.identifier, cookie);
5f4f9f4af   David Howells   CacheFiles: Downg...
35
  	lookup_data = kmalloc(sizeof(*lookup_data), cachefiles_gfp);
9ae326a69   David Howells   CacheFiles: A cac...
36
37
38
39
  	if (!lookup_data)
  		goto nomem_lookup_data;
  
  	/* create a new object record and a temporary leaf image */
5f4f9f4af   David Howells   CacheFiles: Downg...
40
  	object = kmem_cache_alloc(cachefiles_object_jar, cachefiles_gfp);
9ae326a69   David Howells   CacheFiles: A cac...
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  	if (!object)
  		goto nomem_object;
  
  	ASSERTCMP(object->backer, ==, NULL);
  
  	BUG_ON(test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags));
  	atomic_set(&object->usage, 1);
  
  	fscache_object_init(&object->fscache, cookie, &cache->cache);
  
  	object->type = cookie->def->type;
  
  	/* get hold of the raw key
  	 * - stick the length on the front and leave space on the back for the
  	 *   encoder
  	 */
5f4f9f4af   David Howells   CacheFiles: Downg...
57
  	buffer = kmalloc((2 + 512) + 3, cachefiles_gfp);
9ae326a69   David Howells   CacheFiles: A cac...
58
59
  	if (!buffer)
  		goto nomem_buffer;
402cb8dda   David Howells   fscache: Attach t...
60
61
62
63
64
65
  	keylen = cookie->key_len;
  	if (keylen <= sizeof(cookie->inline_key))
  		p = cookie->inline_key;
  	else
  		p = cookie->key;
  	memcpy(buffer + 2, p, keylen);
9ae326a69   David Howells   CacheFiles: A cac...
66
67
68
69
70
71
72
73
74
75
76
77
78
  
  	*(uint16_t *)buffer = keylen;
  	((char *)buffer)[keylen + 2] = 0;
  	((char *)buffer)[keylen + 3] = 0;
  	((char *)buffer)[keylen + 4] = 0;
  
  	/* turn the raw key into something that can work with as a filename */
  	key = cachefiles_cook_key(buffer, keylen + 2, object->type);
  	if (!key)
  		goto nomem_key;
  
  	/* get hold of the auxiliary data and prepend the object type */
  	auxdata = buffer;
402cb8dda   David Howells   fscache: Attach t...
79
80
81
82
83
84
85
  	auxlen = cookie->aux_len;
  	if (auxlen) {
  		if (auxlen <= sizeof(cookie->inline_aux))
  			p = cookie->inline_aux;
  		else
  			p = cookie->aux;
  		memcpy(auxdata->data, p, auxlen);
9ae326a69   David Howells   CacheFiles: A cac...
86
87
88
  	}
  
  	auxdata->len = auxlen + 1;
402cb8dda   David Howells   fscache: Attach t...
89
  	auxdata->type = cookie->type;
9ae326a69   David Howells   CacheFiles: A cac...
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  
  	lookup_data->auxdata = auxdata;
  	lookup_data->key = key;
  	object->lookup_data = lookup_data;
  
  	_leave(" = %p [%p]", &object->fscache, lookup_data);
  	return &object->fscache;
  
  nomem_key:
  	kfree(buffer);
  nomem_buffer:
  	BUG_ON(test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags));
  	kmem_cache_free(cachefiles_object_jar, object);
  	fscache_object_destroyed(&cache->cache);
  nomem_object:
  	kfree(lookup_data);
  nomem_lookup_data:
  	_leave(" = -ENOMEM");
  	return ERR_PTR(-ENOMEM);
  }
  
  /*
   * attempt to look up the nominated node in this cache
fee096deb   David Howells   CacheFiles: Catch...
113
   * - return -ETIMEDOUT to be scheduled again
9ae326a69   David Howells   CacheFiles: A cac...
114
   */
fee096deb   David Howells   CacheFiles: Catch...
115
  static int cachefiles_lookup_object(struct fscache_object *_object)
9ae326a69   David Howells   CacheFiles: A cac...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
  {
  	struct cachefiles_lookup_data *lookup_data;
  	struct cachefiles_object *parent, *object;
  	struct cachefiles_cache *cache;
  	const struct cred *saved_cred;
  	int ret;
  
  	_enter("{OBJ%x}", _object->debug_id);
  
  	cache = container_of(_object->cache, struct cachefiles_cache, cache);
  	parent = container_of(_object->parent,
  			      struct cachefiles_object, fscache);
  	object = container_of(_object, struct cachefiles_object, fscache);
  	lookup_data = object->lookup_data;
  
  	ASSERTCMP(lookup_data, !=, NULL);
  
  	/* look up the key, creating any missing bits */
  	cachefiles_begin_secure(cache, &saved_cred);
  	ret = cachefiles_walk_to_object(parent, object,
  					lookup_data->key,
  					lookup_data->auxdata);
  	cachefiles_end_secure(cache, saved_cred);
  
  	/* polish off by setting the attributes of non-index files */
  	if (ret == 0 &&
  	    object->fscache.cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX)
  		cachefiles_attr_changed(&object->fscache);
fee096deb   David Howells   CacheFiles: Catch...
144
  	if (ret < 0 && ret != -ETIMEDOUT) {
14e69647c   David Howells   CacheFiles: Don't...
145
  		if (ret != -ENOBUFS)
0227d6abb   Fabian Frederick   fs/cachefiles: re...
146
147
  			pr_warn("Lookup failed error %d
  ", ret);
9ae326a69   David Howells   CacheFiles: A cac...
148
149
150
151
  		fscache_object_lookup_error(&object->fscache);
  	}
  
  	_leave(" [%d]", ret);
fee096deb   David Howells   CacheFiles: Catch...
152
  	return ret;
9ae326a69   David Howells   CacheFiles: A cac...
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
  }
  
  /*
   * indication of lookup completion
   */
  static void cachefiles_lookup_complete(struct fscache_object *_object)
  {
  	struct cachefiles_object *object;
  
  	object = container_of(_object, struct cachefiles_object, fscache);
  
  	_enter("{OBJ%x,%p}", object->fscache.debug_id, object->lookup_data);
  
  	if (object->lookup_data) {
  		kfree(object->lookup_data->key);
  		kfree(object->lookup_data->auxdata);
  		kfree(object->lookup_data);
  		object->lookup_data = NULL;
  	}
  }
  
  /*
   * increment the usage count on an inode object (may fail if unmounting)
   */
  static
a18feb557   David Howells   fscache: Add trac...
178
179
  struct fscache_object *cachefiles_grab_object(struct fscache_object *_object,
  					      enum fscache_obj_ref_trace why)
9ae326a69   David Howells   CacheFiles: A cac...
180
181
182
  {
  	struct cachefiles_object *object =
  		container_of(_object, struct cachefiles_object, fscache);
a18feb557   David Howells   fscache: Add trac...
183
  	int u;
9ae326a69   David Howells   CacheFiles: A cac...
184
185
186
187
188
189
  
  	_enter("{OBJ%x,%d}", _object->debug_id, atomic_read(&object->usage));
  
  #ifdef CACHEFILES_DEBUG_SLAB
  	ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
  #endif
a18feb557   David Howells   fscache: Add trac...
190
191
192
  	u = atomic_inc_return(&object->usage);
  	trace_cachefiles_ref(object, _object->cookie,
  			     (enum cachefiles_obj_ref_trace)why, u);
9ae326a69   David Howells   CacheFiles: A cac...
193
194
195
196
  	return &object->fscache;
  }
  
  /*
25985edce   Lucas De Marchi   Fix common misspe...
197
   * update the auxiliary data for an object object on disk
9ae326a69   David Howells   CacheFiles: A cac...
198
199
200
201
202
203
204
205
   */
  static void cachefiles_update_object(struct fscache_object *_object)
  {
  	struct cachefiles_object *object;
  	struct cachefiles_xattr *auxdata;
  	struct cachefiles_cache *cache;
  	struct fscache_cookie *cookie;
  	const struct cred *saved_cred;
402cb8dda   David Howells   fscache: Attach t...
206
  	const void *aux;
9ae326a69   David Howells   CacheFiles: A cac...
207
208
209
210
211
212
213
  	unsigned auxlen;
  
  	_enter("{OBJ%x}", _object->debug_id);
  
  	object = container_of(_object, struct cachefiles_object, fscache);
  	cache = container_of(object->fscache.cache, struct cachefiles_cache,
  			     cache);
1362729b1   David Howells   FS-Cache: Simplif...
214
215
216
217
218
  
  	if (!fscache_use_cookie(_object)) {
  		_leave(" [relinq]");
  		return;
  	}
9ae326a69   David Howells   CacheFiles: A cac...
219
  	cookie = object->fscache.cookie;
402cb8dda   David Howells   fscache: Attach t...
220
  	auxlen = cookie->aux_len;
9ae326a69   David Howells   CacheFiles: A cac...
221

402cb8dda   David Howells   fscache: Attach t...
222
  	if (!auxlen) {
1362729b1   David Howells   FS-Cache: Simplif...
223
  		fscache_unuse_cookie(_object);
9ae326a69   David Howells   CacheFiles: A cac...
224
225
226
  		_leave(" [no aux]");
  		return;
  	}
402cb8dda   David Howells   fscache: Attach t...
227
  	auxdata = kmalloc(2 + auxlen + 3, cachefiles_gfp);
9ae326a69   David Howells   CacheFiles: A cac...
228
  	if (!auxdata) {
1362729b1   David Howells   FS-Cache: Simplif...
229
  		fscache_unuse_cookie(_object);
9ae326a69   David Howells   CacheFiles: A cac...
230
231
232
  		_leave(" [nomem]");
  		return;
  	}
402cb8dda   David Howells   fscache: Attach t...
233
234
235
236
  	aux = (auxlen <= sizeof(cookie->inline_aux)) ?
  		cookie->inline_aux : cookie->aux;
  
  	memcpy(auxdata->data, aux, auxlen);
1362729b1   David Howells   FS-Cache: Simplif...
237
  	fscache_unuse_cookie(_object);
9ae326a69   David Howells   CacheFiles: A cac...
238
239
  
  	auxdata->len = auxlen + 1;
402cb8dda   David Howells   fscache: Attach t...
240
  	auxdata->type = cookie->type;
9ae326a69   David Howells   CacheFiles: A cac...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
  
  	cachefiles_begin_secure(cache, &saved_cred);
  	cachefiles_update_object_xattr(object, auxdata);
  	cachefiles_end_secure(cache, saved_cred);
  	kfree(auxdata);
  	_leave("");
  }
  
  /*
   * discard the resources pinned by an object and effect retirement if
   * requested
   */
  static void cachefiles_drop_object(struct fscache_object *_object)
  {
  	struct cachefiles_object *object;
  	struct cachefiles_cache *cache;
  	const struct cred *saved_cred;
a818101d7   David Howells   cachefiles: Fix a...
258
259
  	struct inode *inode;
  	blkcnt_t i_blocks = 0;
9ae326a69   David Howells   CacheFiles: A cac...
260
261
262
263
264
265
266
267
268
269
270
271
272
273
  
  	ASSERT(_object);
  
  	object = container_of(_object, struct cachefiles_object, fscache);
  
  	_enter("{OBJ%x,%d}",
  	       object->fscache.debug_id, atomic_read(&object->usage));
  
  	cache = container_of(object->fscache.cache,
  			     struct cachefiles_cache, cache);
  
  #ifdef CACHEFILES_DEBUG_SLAB
  	ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
  #endif
a3b7c0048   David Howells   CacheFiles: Handl...
274
275
276
277
278
279
280
281
282
283
284
  	/* We need to tidy the object up if we did in fact manage to open it.
  	 * It's possible for us to get here before the object is fully
  	 * initialised if the parent goes away or the object gets retired
  	 * before we set it up.
  	 */
  	if (object->dentry) {
  		/* delete retired objects */
  		if (test_bit(FSCACHE_OBJECT_RETIRED, &object->fscache.flags) &&
  		    _object != cache->cache.fsdef
  		    ) {
  			_debug("- retire object OBJ%x", object->fscache.debug_id);
a818101d7   David Howells   cachefiles: Fix a...
285
286
287
  			inode = d_backing_inode(object->dentry);
  			if (inode)
  				i_blocks = inode->i_blocks;
a3b7c0048   David Howells   CacheFiles: Handl...
288
289
290
291
292
293
294
295
296
  			cachefiles_begin_secure(cache, &saved_cred);
  			cachefiles_delete_object(cache, object);
  			cachefiles_end_secure(cache, saved_cred);
  		}
  
  		/* close the filesystem stuff attached to the object */
  		if (object->backer != object->dentry)
  			dput(object->backer);
  		object->backer = NULL;
9ae326a69   David Howells   CacheFiles: A cac...
297
  	}
9ae326a69   David Howells   CacheFiles: A cac...
298
  	/* note that the object is now inactive */
a5b3a80b8   David Howells   CacheFiles: Provi...
299
  	if (test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags))
a818101d7   David Howells   cachefiles: Fix a...
300
  		cachefiles_mark_object_inactive(cache, object, i_blocks);
9ae326a69   David Howells   CacheFiles: A cac...
301
302
303
304
305
306
307
308
309
310
  
  	dput(object->dentry);
  	object->dentry = NULL;
  
  	_leave("");
  }
  
  /*
   * dispose of a reference to an object
   */
a18feb557   David Howells   fscache: Add trac...
311
312
  static void cachefiles_put_object(struct fscache_object *_object,
  				  enum fscache_obj_ref_trace why)
9ae326a69   David Howells   CacheFiles: A cac...
313
314
315
  {
  	struct cachefiles_object *object;
  	struct fscache_cache *cache;
a18feb557   David Howells   fscache: Add trac...
316
  	int u;
9ae326a69   David Howells   CacheFiles: A cac...
317
318
319
320
321
322
323
324
325
326
327
328
329
330
  
  	ASSERT(_object);
  
  	object = container_of(_object, struct cachefiles_object, fscache);
  
  	_enter("{OBJ%x,%d}",
  	       object->fscache.debug_id, atomic_read(&object->usage));
  
  #ifdef CACHEFILES_DEBUG_SLAB
  	ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
  #endif
  
  	ASSERTIFCMP(object->fscache.parent,
  		    object->fscache.parent->n_children, >, 0);
a18feb557   David Howells   fscache: Add trac...
331
332
333
334
335
  	u = atomic_dec_return(&object->usage);
  	trace_cachefiles_ref(object, _object->cookie,
  			     (enum cachefiles_obj_ref_trace)why, u);
  	ASSERTCMP(u, !=, -1);
  	if (u == 0) {
9ae326a69   David Howells   CacheFiles: A cac...
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
  		_debug("- kill object OBJ%x", object->fscache.debug_id);
  
  		ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags));
  		ASSERTCMP(object->fscache.parent, ==, NULL);
  		ASSERTCMP(object->backer, ==, NULL);
  		ASSERTCMP(object->dentry, ==, NULL);
  		ASSERTCMP(object->fscache.n_ops, ==, 0);
  		ASSERTCMP(object->fscache.n_children, ==, 0);
  
  		if (object->lookup_data) {
  			kfree(object->lookup_data->key);
  			kfree(object->lookup_data->auxdata);
  			kfree(object->lookup_data);
  			object->lookup_data = NULL;
  		}
  
  		cache = object->fscache.cache;
4fbf4291a   David Howells   FS-Cache: Allow t...
353
  		fscache_object_destroy(&object->fscache);
9ae326a69   David Howells   CacheFiles: A cac...
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
  		kmem_cache_free(cachefiles_object_jar, object);
  		fscache_object_destroyed(cache);
  	}
  
  	_leave("");
  }
  
  /*
   * sync a cache
   */
  static void cachefiles_sync_cache(struct fscache_cache *_cache)
  {
  	struct cachefiles_cache *cache;
  	const struct cred *saved_cred;
  	int ret;
  
  	_enter("%p", _cache);
  
  	cache = container_of(_cache, struct cachefiles_cache, cache);
  
  	/* make sure all pages pinned by operations on behalf of the netfs are
  	 * written to disc */
  	cachefiles_begin_secure(cache, &saved_cred);
5af7926ff   Christoph Hellwig   enforce ->sync_fs...
377
  	down_read(&cache->mnt->mnt_sb->s_umount);
60b0680fa   Jan Kara   vfs: Rename fsync...
378
  	ret = sync_filesystem(cache->mnt->mnt_sb);
5af7926ff   Christoph Hellwig   enforce ->sync_fs...
379
  	up_read(&cache->mnt->mnt_sb->s_umount);
9ae326a69   David Howells   CacheFiles: A cac...
380
381
382
383
384
385
386
387
388
389
  	cachefiles_end_secure(cache, saved_cred);
  
  	if (ret == -EIO)
  		cachefiles_io_error(cache,
  				    "Attempt to sync backing fs superblock"
  				    " returned error %d",
  				    ret);
  }
  
  /*
5002d7bef   David Howells   CacheFiles: Imple...
390
391
392
   * check if the backing cache is updated to FS-Cache
   * - called by FS-Cache when evaluates if need to invalidate the cache
   */
480ce08a7   Yan, Zheng   FS-Cache: make ch...
393
  static int cachefiles_check_consistency(struct fscache_operation *op)
5002d7bef   David Howells   CacheFiles: Imple...
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
  {
  	struct cachefiles_object *object;
  	struct cachefiles_cache *cache;
  	const struct cred *saved_cred;
  	int ret;
  
  	_enter("{OBJ%x}", op->object->debug_id);
  
  	object = container_of(op->object, struct cachefiles_object, fscache);
  	cache = container_of(object->fscache.cache,
  			     struct cachefiles_cache, cache);
  
  	cachefiles_begin_secure(cache, &saved_cred);
  	ret = cachefiles_check_auxdata(object);
  	cachefiles_end_secure(cache, saved_cred);
  
  	_leave(" = %d", ret);
  	return ret;
  }
  
  /*
9ae326a69   David Howells   CacheFiles: A cac...
415
416
417
418
419
420
421
422
423
424
425
426
   * notification the attributes on an object have changed
   * - called with reads/writes excluded by FS-Cache
   */
  static int cachefiles_attr_changed(struct fscache_object *_object)
  {
  	struct cachefiles_object *object;
  	struct cachefiles_cache *cache;
  	const struct cred *saved_cred;
  	struct iattr newattrs;
  	uint64_t ni_size;
  	loff_t oi_size;
  	int ret;
ee1235a9a   David Howells   fscache: Pass obj...
427
  	ni_size = _object->store_limit_l;
9ae326a69   David Howells   CacheFiles: A cac...
428
429
430
431
432
433
434
435
436
437
438
439
440
  
  	_enter("{OBJ%x},[%llu]",
  	       _object->debug_id, (unsigned long long) ni_size);
  
  	object = container_of(_object, struct cachefiles_object, fscache);
  	cache = container_of(object->fscache.cache,
  			     struct cachefiles_cache, cache);
  
  	if (ni_size == object->i_size)
  		return 0;
  
  	if (!object->backer)
  		return -ENOBUFS;
ce40fa78e   David Howells   Cachefiles: Fix u...
441
  	ASSERT(d_is_reg(object->backer));
9ae326a69   David Howells   CacheFiles: A cac...
442
443
  
  	fscache_set_store_limit(&object->fscache, ni_size);
466b77bc9   David Howells   VFS: fs/cachefile...
444
  	oi_size = i_size_read(d_backing_inode(object->backer));
9ae326a69   David Howells   CacheFiles: A cac...
445
446
  	if (oi_size == ni_size)
  		return 0;
9ae326a69   David Howells   CacheFiles: A cac...
447
  	cachefiles_begin_secure(cache, &saved_cred);
5955102c9   Al Viro   wrappers for ->i_...
448
  	inode_lock(d_inode(object->backer));
a17754fb8   David Howells   CacheFiles: Don't...
449
450
451
452
453
454
455
456
  
  	/* if there's an extension to a partial page at the end of the backing
  	 * file, we need to discard the partial page so that we pick up new
  	 * data after it */
  	if (oi_size & ~PAGE_MASK && ni_size > oi_size) {
  		_debug("discard tail %llx", oi_size);
  		newattrs.ia_valid = ATTR_SIZE;
  		newattrs.ia_size = oi_size & PAGE_MASK;
27ac0ffea   J. Bruce Fields   locks: break dele...
457
  		ret = notify_change(object->backer, &newattrs, NULL);
a17754fb8   David Howells   CacheFiles: Don't...
458
459
460
461
462
463
  		if (ret < 0)
  			goto truncate_failed;
  	}
  
  	newattrs.ia_valid = ATTR_SIZE;
  	newattrs.ia_size = ni_size;
27ac0ffea   J. Bruce Fields   locks: break dele...
464
  	ret = notify_change(object->backer, &newattrs, NULL);
a17754fb8   David Howells   CacheFiles: Don't...
465
466
  
  truncate_failed:
5955102c9   Al Viro   wrappers for ->i_...
467
  	inode_unlock(d_inode(object->backer));
9ae326a69   David Howells   CacheFiles: A cac...
468
469
470
471
472
473
474
475
476
477
478
479
480
  	cachefiles_end_secure(cache, saved_cred);
  
  	if (ret == -EIO) {
  		fscache_set_store_limit(&object->fscache, 0);
  		cachefiles_io_error_obj(object, "Size set failed");
  		ret = -ENOBUFS;
  	}
  
  	_leave(" = %d", ret);
  	return ret;
  }
  
  /*
9dc8d9bfe   David Howells   CacheFiles: Imple...
481
482
483
484
485
486
487
488
489
490
491
492
493
494
   * Invalidate an object
   */
  static void cachefiles_invalidate_object(struct fscache_operation *op)
  {
  	struct cachefiles_object *object;
  	struct cachefiles_cache *cache;
  	const struct cred *saved_cred;
  	struct path path;
  	uint64_t ni_size;
  	int ret;
  
  	object = container_of(op->object, struct cachefiles_object, fscache);
  	cache = container_of(object->fscache.cache,
  			     struct cachefiles_cache, cache);
ee1235a9a   David Howells   fscache: Pass obj...
495
  	ni_size = op->object->store_limit_l;
9dc8d9bfe   David Howells   CacheFiles: Imple...
496
497
498
499
500
  
  	_enter("{OBJ%x},[%llu]",
  	       op->object->debug_id, (unsigned long long)ni_size);
  
  	if (object->backer) {
ce40fa78e   David Howells   Cachefiles: Fix u...
501
  		ASSERT(d_is_reg(object->backer));
9dc8d9bfe   David Howells   CacheFiles: Imple...
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
  
  		fscache_set_store_limit(&object->fscache, ni_size);
  
  		path.dentry = object->backer;
  		path.mnt = cache->mnt;
  
  		cachefiles_begin_secure(cache, &saved_cred);
  		ret = vfs_truncate(&path, 0);
  		if (ret == 0)
  			ret = vfs_truncate(&path, ni_size);
  		cachefiles_end_secure(cache, saved_cred);
  
  		if (ret != 0) {
  			fscache_set_store_limit(&object->fscache, 0);
  			if (ret == -EIO)
  				cachefiles_io_error_obj(object,
  							"Invalidate failed");
  		}
  	}
1f372dff1   David Howells   FS-Cache: Mark ca...
521
  	fscache_op_complete(op, true);
9dc8d9bfe   David Howells   CacheFiles: Imple...
522
523
524
525
  	_leave("");
  }
  
  /*
9ae326a69   David Howells   CacheFiles: A cac...
526
527
528
529
530
531
532
533
534
535
536
537
538
539
   * dissociate a cache from all the pages it was backing
   */
  static void cachefiles_dissociate_pages(struct fscache_cache *cache)
  {
  	_enter("");
  }
  
  const struct fscache_cache_ops cachefiles_cache_ops = {
  	.name			= "cachefiles",
  	.alloc_object		= cachefiles_alloc_object,
  	.lookup_object		= cachefiles_lookup_object,
  	.lookup_complete	= cachefiles_lookup_complete,
  	.grab_object		= cachefiles_grab_object,
  	.update_object		= cachefiles_update_object,
9dc8d9bfe   David Howells   CacheFiles: Imple...
540
  	.invalidate_object	= cachefiles_invalidate_object,
9ae326a69   David Howells   CacheFiles: A cac...
541
542
543
544
545
546
547
548
549
550
551
  	.drop_object		= cachefiles_drop_object,
  	.put_object		= cachefiles_put_object,
  	.sync_cache		= cachefiles_sync_cache,
  	.attr_changed		= cachefiles_attr_changed,
  	.read_or_alloc_page	= cachefiles_read_or_alloc_page,
  	.read_or_alloc_pages	= cachefiles_read_or_alloc_pages,
  	.allocate_page		= cachefiles_allocate_page,
  	.allocate_pages		= cachefiles_allocate_pages,
  	.write_page		= cachefiles_write_page,
  	.uncache_page		= cachefiles_uncache_page,
  	.dissociate_pages	= cachefiles_dissociate_pages,
5002d7bef   David Howells   CacheFiles: Imple...
552
  	.check_consistency	= cachefiles_check_consistency,
9ae326a69   David Howells   CacheFiles: A cac...
553
  };