aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cachefiles
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2012-12-20 16:52:36 -0500
committerDavid Howells <dhowells@redhat.com>2012-12-20 17:06:08 -0500
commit9dc8d9bfe4415efb61a5e9390706b8a3bffef329 (patch)
tree2534486c442b7889a761d894f3bd4dd0403608ca /fs/cachefiles
parenta02de9608595c8ef649ef03ae735b0b45e3d4396 (diff)
CacheFiles: Implement invalidation
Implement invalidation for CacheFiles. This is in two parts: (1) Provide an invalidation method (which just truncates the backing file). (2) Abort attempts to copy anything read from the backing file whilst invalidation is in progress. Question: CacheFiles uses truncation in a couple of places. It has been using notify_change() rather than sys_truncate() or something similar. This means it bypasses a bunch of checks and suchlike that it possibly should be making (security, file locking, lease breaking, vfsmount write). Should it be using vfs_truncate() as added by a preceding patch or should it use notify_write() and assume that anyone poking around in the cache files on disk gets everything they deserve? Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/cachefiles')
-rw-r--r--fs/cachefiles/interface.c49
-rw-r--r--fs/cachefiles/rdwr.c5
2 files changed, 53 insertions, 1 deletions
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c
index 9bff0f878cfd..7a9d574b961c 100644
--- a/fs/cachefiles/interface.c
+++ b/fs/cachefiles/interface.c
@@ -441,6 +441,54 @@ truncate_failed:
441} 441}
442 442
443/* 443/*
444 * Invalidate an object
445 */
446static void cachefiles_invalidate_object(struct fscache_operation *op)
447{
448 struct cachefiles_object *object;
449 struct cachefiles_cache *cache;
450 const struct cred *saved_cred;
451 struct path path;
452 uint64_t ni_size;
453 int ret;
454
455 object = container_of(op->object, struct cachefiles_object, fscache);
456 cache = container_of(object->fscache.cache,
457 struct cachefiles_cache, cache);
458
459 op->object->cookie->def->get_attr(op->object->cookie->netfs_data,
460 &ni_size);
461
462 _enter("{OBJ%x},[%llu]",
463 op->object->debug_id, (unsigned long long)ni_size);
464
465 if (object->backer) {
466 ASSERT(S_ISREG(object->backer->d_inode->i_mode));
467
468 fscache_set_store_limit(&object->fscache, ni_size);
469
470 path.dentry = object->backer;
471 path.mnt = cache->mnt;
472
473 cachefiles_begin_secure(cache, &saved_cred);
474 ret = vfs_truncate(&path, 0);
475 if (ret == 0)
476 ret = vfs_truncate(&path, ni_size);
477 cachefiles_end_secure(cache, saved_cred);
478
479 if (ret != 0) {
480 fscache_set_store_limit(&object->fscache, 0);
481 if (ret == -EIO)
482 cachefiles_io_error_obj(object,
483 "Invalidate failed");
484 }
485 }
486
487 fscache_op_complete(op);
488 _leave("");
489}
490
491/*
444 * dissociate a cache from all the pages it was backing 492 * dissociate a cache from all the pages it was backing
445 */ 493 */
446static void cachefiles_dissociate_pages(struct fscache_cache *cache) 494static void cachefiles_dissociate_pages(struct fscache_cache *cache)
@@ -455,6 +503,7 @@ const struct fscache_cache_ops cachefiles_cache_ops = {
455 .lookup_complete = cachefiles_lookup_complete, 503 .lookup_complete = cachefiles_lookup_complete,
456 .grab_object = cachefiles_grab_object, 504 .grab_object = cachefiles_grab_object,
457 .update_object = cachefiles_update_object, 505 .update_object = cachefiles_update_object,
506 .invalidate_object = cachefiles_invalidate_object,
458 .drop_object = cachefiles_drop_object, 507 .drop_object = cachefiles_drop_object,
459 .put_object = cachefiles_put_object, 508 .put_object = cachefiles_put_object,
460 .sync_cache = cachefiles_sync_cache, 509 .sync_cache = cachefiles_sync_cache,
diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c
index 93a0815e0498..2c994885520a 100644
--- a/fs/cachefiles/rdwr.c
+++ b/fs/cachefiles/rdwr.c
@@ -174,7 +174,10 @@ static void cachefiles_read_copier(struct fscache_operation *_op)
174 _debug("- copy {%lu}", monitor->back_page->index); 174 _debug("- copy {%lu}", monitor->back_page->index);
175 175
176 recheck: 176 recheck:
177 if (PageUptodate(monitor->back_page)) { 177 if (test_bit(FSCACHE_COOKIE_INVALIDATING,
178 &object->fscache.cookie->flags)) {
179 error = -ESTALE;
180 } else if (PageUptodate(monitor->back_page)) {
178 copy_highpage(monitor->netfs_page, monitor->back_page); 181 copy_highpage(monitor->netfs_page, monitor->back_page);
179 fscache_mark_page_cached(monitor->op, 182 fscache_mark_page_cached(monitor->op,
180 monitor->netfs_page); 183 monitor->netfs_page);