diff options
Diffstat (limited to 'fs/cachefiles/interface.c')
| -rw-r--r-- | fs/cachefiles/interface.c | 106 | 
1 files changed, 93 insertions, 13 deletions
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index 37fe101a4e0..584743d456c 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -11,11 +11,8 @@  #include <linux/slab.h>  #include <linux/mount.h> -#include <linux/buffer_head.h>  #include "internal.h" -#define list_to_page(head) (list_entry((head)->prev, struct page, lru)) -  struct cachefiles_lookup_data {  	struct cachefiles_xattr	*auxdata;	/* auxiliary data */  	char			*key;		/* key path */ @@ -42,12 +39,12 @@ static struct fscache_object *cachefiles_alloc_object(  	_enter("{%s},%p,", cache->cache.identifier, cookie); -	lookup_data = kmalloc(sizeof(*lookup_data), GFP_KERNEL); +	lookup_data = kmalloc(sizeof(*lookup_data), cachefiles_gfp);  	if (!lookup_data)  		goto nomem_lookup_data;  	/* create a new object record and a temporary leaf image */ -	object = kmem_cache_alloc(cachefiles_object_jar, GFP_KERNEL); +	object = kmem_cache_alloc(cachefiles_object_jar, cachefiles_gfp);  	if (!object)  		goto nomem_object; @@ -64,7 +61,7 @@ static struct fscache_object *cachefiles_alloc_object(  	 * - stick the length on the front and leave space on the back for the  	 *   encoder  	 */ -	buffer = kmalloc((2 + 512) + 3, GFP_KERNEL); +	buffer = kmalloc((2 + 512) + 3, cachefiles_gfp);  	if (!buffer)  		goto nomem_buffer; @@ -149,8 +146,7 @@ static int cachefiles_lookup_object(struct fscache_object *_object)  	if (ret < 0 && ret != -ETIMEDOUT) {  		if (ret != -ENOBUFS) -			printk(KERN_WARNING -			       "CacheFiles: Lookup failed error %d\n", ret); +			pr_warn("Lookup failed error %d\n", ret);  		fscache_object_lookup_error(&object->fscache);  	} @@ -197,7 +193,7 @@ struct fscache_object *cachefiles_grab_object(struct fscache_object *_object)  }  /* - * update the auxilliary data for an object object on disk + * update the auxiliary data for an object object on disk   */  static void cachefiles_update_object(struct fscache_object *_object)  { @@ -213,20 +209,29 @@ static void cachefiles_update_object(struct fscache_object *_object)  	object = container_of(_object, struct cachefiles_object, fscache);  	cache = container_of(object->fscache.cache, struct cachefiles_cache,  			     cache); + +	if (!fscache_use_cookie(_object)) { +		_leave(" [relinq]"); +		return; +	} +  	cookie = object->fscache.cookie;  	if (!cookie->def->get_aux) { +		fscache_unuse_cookie(_object);  		_leave(" [no aux]");  		return;  	} -	auxdata = kmalloc(2 + 512 + 3, GFP_KERNEL); +	auxdata = kmalloc(2 + 512 + 3, cachefiles_gfp);  	if (!auxdata) { +		fscache_unuse_cookie(_object);  		_leave(" [nomem]");  		return;  	}  	auxlen = cookie->def->get_aux(cookie->netfs_data, auxdata->data, 511); +	fscache_unuse_cookie(_object);  	ASSERTCMP(auxlen, <, 511);  	auxdata->len = auxlen + 1; @@ -264,7 +269,7 @@ static void cachefiles_drop_object(struct fscache_object *_object)  #endif  	/* delete retired objects */ -	if (object->fscache.state == FSCACHE_OBJECT_RECYCLING && +	if (test_bit(FSCACHE_OBJECT_RETIRED, &object->fscache.flags) &&  	    _object != cache->cache.fsdef  	    ) {  		_debug("- retire object OBJ%x", object->fscache.debug_id); @@ -372,6 +377,31 @@ static void cachefiles_sync_cache(struct fscache_cache *_cache)  }  /* + * check if the backing cache is updated to FS-Cache + * - called by FS-Cache when evaluates if need to invalidate the cache + */ +static bool cachefiles_check_consistency(struct fscache_operation *op) +{ +	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; +} + +/*   * notification the attributes on an object have changed   * - called with reads/writes excluded by FS-Cache   */ @@ -418,14 +448,14 @@ static int cachefiles_attr_changed(struct fscache_object *_object)  		_debug("discard tail %llx", oi_size);  		newattrs.ia_valid = ATTR_SIZE;  		newattrs.ia_size = oi_size & PAGE_MASK; -		ret = notify_change(object->backer, &newattrs); +		ret = notify_change(object->backer, &newattrs, NULL);  		if (ret < 0)  			goto truncate_failed;  	}  	newattrs.ia_valid = ATTR_SIZE;  	newattrs.ia_size = ni_size; -	ret = notify_change(object->backer, &newattrs); +	ret = notify_change(object->backer, &newattrs, NULL);  truncate_failed:  	mutex_unlock(&object->backer->d_inode->i_mutex); @@ -442,6 +472,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, true); +	_leave(""); +} + +/*   * dissociate a cache from all the pages it was backing   */  static void cachefiles_dissociate_pages(struct fscache_cache *cache) @@ -456,6 +534,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, @@ -467,4 +546,5 @@ const struct fscache_cache_ops cachefiles_cache_ops = {  	.write_page		= cachefiles_write_page,  	.uncache_page		= cachefiles_uncache_page,  	.dissociate_pages	= cachefiles_dissociate_pages, +	.check_consistency	= cachefiles_check_consistency,  };  | 
