diff options
| author | David Howells <dhowells@redhat.com> | 2012-12-20 21:52:36 +0000 | 
|---|---|---|
| committer | David Howells <dhowells@redhat.com> | 2012-12-20 22:06:08 +0000 | 
| commit | 9dc8d9bfe4415efb61a5e9390706b8a3bffef329 (patch) | |
| tree | 2534486c442b7889a761d894f3bd4dd0403608ca /fs/cachefiles/interface.c | |
| parent | a02de9608595c8ef649ef03ae735b0b45e3d4396 (diff) | |
| download | olio-linux-3.10-9dc8d9bfe4415efb61a5e9390706b8a3bffef329.tar.xz olio-linux-3.10-9dc8d9bfe4415efb61a5e9390706b8a3bffef329.zip  | |
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/interface.c')
| -rw-r--r-- | fs/cachefiles/interface.c | 49 | 
1 files changed, 49 insertions, 0 deletions
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index 9bff0f878cf..7a9d574b961 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -441,6 +441,54 @@ truncate_failed:  }  /* + * 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   */  static void cachefiles_dissociate_pages(struct fscache_cache *cache) @@ -455,6 +503,7 @@ const struct fscache_cache_ops cachefiles_cache_ops = {  	.lookup_complete	= cachefiles_lookup_complete,  	.grab_object		= cachefiles_grab_object,  	.update_object		= cachefiles_update_object, +	.invalidate_object	= cachefiles_invalidate_object,  	.drop_object		= cachefiles_drop_object,  	.put_object		= cachefiles_put_object,  	.sync_cache		= cachefiles_sync_cache,  |