Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9dc8d9bf authored by David Howells's avatar David Howells
Browse files

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: default avatarDavid Howells <dhowells@redhat.com>
parent a02de960
Loading
Loading
Loading
Loading
+49 −0
Original line number Original line Diff line number Diff line
@@ -440,6 +440,54 @@ truncate_failed:
	return ret;
	return ret;
}
}


/*
 * 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);

	op->object->cookie->def->get_attr(op->object->cookie->netfs_data,
					  &ni_size);

	_enter("{OBJ%x},[%llu]",
	       op->object->debug_id, (unsigned long long)ni_size);

	if (object->backer) {
		ASSERT(S_ISREG(object->backer->d_inode->i_mode));

		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");
		}
	}

	fscache_op_complete(op);
	_leave("");
}

/*
/*
 * dissociate a cache from all the pages it was backing
 * dissociate a cache from all the pages it was backing
 */
 */
@@ -455,6 +503,7 @@ const struct fscache_cache_ops cachefiles_cache_ops = {
	.lookup_complete	= cachefiles_lookup_complete,
	.lookup_complete	= cachefiles_lookup_complete,
	.grab_object		= cachefiles_grab_object,
	.grab_object		= cachefiles_grab_object,
	.update_object		= cachefiles_update_object,
	.update_object		= cachefiles_update_object,
	.invalidate_object	= cachefiles_invalidate_object,
	.drop_object		= cachefiles_drop_object,
	.drop_object		= cachefiles_drop_object,
	.put_object		= cachefiles_put_object,
	.put_object		= cachefiles_put_object,
	.sync_cache		= cachefiles_sync_cache,
	.sync_cache		= cachefiles_sync_cache,
+4 −1
Original line number Original line Diff line number Diff line
@@ -174,7 +174,10 @@ static void cachefiles_read_copier(struct fscache_operation *_op)
		_debug("- copy {%lu}", monitor->back_page->index);
		_debug("- copy {%lu}", monitor->back_page->index);


	recheck:
	recheck:
		if (PageUptodate(monitor->back_page)) {
		if (test_bit(FSCACHE_COOKIE_INVALIDATING,
			     &object->fscache.cookie->flags)) {
			error = -ESTALE;
		} else if (PageUptodate(monitor->back_page)) {
			copy_highpage(monitor->netfs_page, monitor->back_page);
			copy_highpage(monitor->netfs_page, monitor->back_page);
			fscache_mark_page_cached(monitor->op,
			fscache_mark_page_cached(monitor->op,
						 monitor->netfs_page);
						 monitor->netfs_page);