diff options
Diffstat (limited to 'fs/cachefiles')
| -rw-r--r-- | fs/cachefiles/bind.c | 20 | ||||
| -rw-r--r-- | fs/cachefiles/daemon.c | 31 | ||||
| -rw-r--r-- | fs/cachefiles/interface.c | 106 | ||||
| -rw-r--r-- | fs/cachefiles/internal.h | 33 | ||||
| -rw-r--r-- | fs/cachefiles/key.c | 2 | ||||
| -rw-r--r-- | fs/cachefiles/main.c | 9 | ||||
| -rw-r--r-- | fs/cachefiles/namei.c | 128 | ||||
| -rw-r--r-- | fs/cachefiles/rdwr.c | 171 | ||||
| -rw-r--r-- | fs/cachefiles/security.c | 10 | ||||
| -rw-r--r-- | fs/cachefiles/xattr.c | 55 | 
10 files changed, 353 insertions, 212 deletions
diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c index a2603e7c0bb..d749731dc0e 100644 --- a/fs/cachefiles/bind.c +++ b/fs/cachefiles/bind.c @@ -50,18 +50,18 @@ int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args)  	       cache->brun_percent  < 100);  	if (*args) { -		kerror("'bind' command doesn't take an argument"); +		pr_err("'bind' command doesn't take an argument");  		return -EINVAL;  	}  	if (!cache->rootdirname) { -		kerror("No cache directory specified"); +		pr_err("No cache directory specified");  		return -EINVAL;  	}  	/* don't permit already bound caches to be re-bound */  	if (test_bit(CACHEFILES_READY, &cache->flags)) { -		kerror("Cache already bound"); +		pr_err("Cache already bound");  		return -EBUSY;  	} @@ -124,13 +124,10 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)  	/* check parameters */  	ret = -EOPNOTSUPP;  	if (!root->d_inode || -	    !root->d_inode->i_op ||  	    !root->d_inode->i_op->lookup ||  	    !root->d_inode->i_op->mkdir ||  	    !root->d_inode->i_op->setxattr ||  	    !root->d_inode->i_op->getxattr || -	    !root->d_sb || -	    !root->d_sb->s_op ||  	    !root->d_sb->s_op->statfs ||  	    !root->d_sb->s_op->sync_fs)  		goto error_unsupported; @@ -231,9 +228,7 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)  	set_bit(CACHEFILES_READY, &cache->flags);  	dput(root); -	printk(KERN_INFO "CacheFiles:" -	       " File cache on %s registered\n", -	       cache->cache.identifier); +	pr_info("File cache on %s registered\n", cache->cache.identifier);  	/* check how much space the cache has */  	cachefiles_has_space(cache, 0, 0); @@ -253,7 +248,7 @@ error_open_root:  	kmem_cache_free(cachefiles_object_jar, fsdef);  error_root_object:  	cachefiles_end_secure(cache, saved_cred); -	kerror("Failed to register: %d", ret); +	pr_err("Failed to register: %d", ret);  	return ret;  } @@ -265,9 +260,8 @@ void cachefiles_daemon_unbind(struct cachefiles_cache *cache)  	_enter("");  	if (test_bit(CACHEFILES_READY, &cache->flags)) { -		printk(KERN_INFO "CacheFiles:" -		       " File cache on %s unregistering\n", -		       cache->cache.identifier); +		pr_info("File cache on %s unregistering\n", +			cache->cache.identifier);  		fscache_withdraw_cache(&cache->cache);  	} diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c index 0a1467b1551..b078d3081d6 100644 --- a/fs/cachefiles/daemon.c +++ b/fs/cachefiles/daemon.c @@ -315,8 +315,7 @@ static unsigned int cachefiles_daemon_poll(struct file *file,  static int cachefiles_daemon_range_error(struct cachefiles_cache *cache,  					 char *args)  { -	kerror("Free space limits must be in range" -	       " 0%%<=stop<cull<run<100%%"); +	pr_err("Free space limits must be in range 0%%<=stop<cull<run<100%%");  	return -EINVAL;  } @@ -476,12 +475,12 @@ static int cachefiles_daemon_dir(struct cachefiles_cache *cache, char *args)  	_enter(",%s", args);  	if (!*args) { -		kerror("Empty directory specified"); +		pr_err("Empty directory specified");  		return -EINVAL;  	}  	if (cache->rootdirname) { -		kerror("Second cache directory specified"); +		pr_err("Second cache directory specified");  		return -EEXIST;  	} @@ -504,12 +503,12 @@ static int cachefiles_daemon_secctx(struct cachefiles_cache *cache, char *args)  	_enter(",%s", args);  	if (!*args) { -		kerror("Empty security context specified"); +		pr_err("Empty security context specified");  		return -EINVAL;  	}  	if (cache->secctx) { -		kerror("Second security context specified"); +		pr_err("Second security context specified");  		return -EINVAL;  	} @@ -532,7 +531,7 @@ static int cachefiles_daemon_tag(struct cachefiles_cache *cache, char *args)  	_enter(",%s", args);  	if (!*args) { -		kerror("Empty tag specified"); +		pr_err("Empty tag specified");  		return -EINVAL;  	} @@ -563,12 +562,12 @@ static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args)  		goto inval;  	if (!test_bit(CACHEFILES_READY, &cache->flags)) { -		kerror("cull applied to unready cache"); +		pr_err("cull applied to unready cache");  		return -EIO;  	}  	if (test_bit(CACHEFILES_DEAD, &cache->flags)) { -		kerror("cull applied to dead cache"); +		pr_err("cull applied to dead cache");  		return -EIO;  	} @@ -588,11 +587,11 @@ static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args)  notdir:  	path_put(&path); -	kerror("cull command requires dirfd to be a directory"); +	pr_err("cull command requires dirfd to be a directory");  	return -ENOTDIR;  inval: -	kerror("cull command requires dirfd and filename"); +	pr_err("cull command requires dirfd and filename");  	return -EINVAL;  } @@ -615,7 +614,7 @@ static int cachefiles_daemon_debug(struct cachefiles_cache *cache, char *args)  	return 0;  inval: -	kerror("debug command requires mask"); +	pr_err("debug command requires mask");  	return -EINVAL;  } @@ -635,12 +634,12 @@ static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args)  		goto inval;  	if (!test_bit(CACHEFILES_READY, &cache->flags)) { -		kerror("inuse applied to unready cache"); +		pr_err("inuse applied to unready cache");  		return -EIO;  	}  	if (test_bit(CACHEFILES_DEAD, &cache->flags)) { -		kerror("inuse applied to dead cache"); +		pr_err("inuse applied to dead cache");  		return -EIO;  	} @@ -660,11 +659,11 @@ static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args)  notdir:  	path_put(&path); -	kerror("inuse command requires dirfd to be a directory"); +	pr_err("inuse command requires dirfd to be a directory");  	return -ENOTDIR;  inval: -	kerror("inuse command requires dirfd and filename"); +	pr_err("inuse command requires dirfd and filename");  	return -EINVAL;  } 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,  }; diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index bd6bc1bde2d..3d50998abf5 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h @@ -9,6 +9,13 @@   * 2 of the Licence, or (at your option) any later version.   */ +#ifdef pr_fmt +#undef pr_fmt +#endif + +#define pr_fmt(fmt) "CacheFiles: " fmt + +  #include <linux/fscache-cache.h>  #include <linux/timer.h>  #include <linux/wait.h> @@ -23,6 +30,8 @@ extern unsigned cachefiles_debug;  #define CACHEFILES_DEBUG_KLEAVE	2  #define CACHEFILES_DEBUG_KDEBUG	4 +#define cachefiles_gfp (__GFP_WAIT | __GFP_NORETRY | __GFP_NOMEMALLOC) +  /*   * node records   */ @@ -233,6 +242,7 @@ extern int cachefiles_set_object_xattr(struct cachefiles_object *object,  				       struct cachefiles_xattr *auxdata);  extern int cachefiles_update_object_xattr(struct cachefiles_object *object,  					  struct cachefiles_xattr *auxdata); +extern int cachefiles_check_auxdata(struct cachefiles_object *object);  extern int cachefiles_check_object_xattr(struct cachefiles_object *object,  					 struct cachefiles_xattr *auxdata);  extern int cachefiles_remove_object_xattr(struct cachefiles_cache *cache, @@ -242,11 +252,10 @@ extern int cachefiles_remove_object_xattr(struct cachefiles_cache *cache,  /*   * error handling   */ -#define kerror(FMT, ...) printk(KERN_ERR "CacheFiles: "FMT"\n", ##__VA_ARGS__)  #define cachefiles_io_error(___cache, FMT, ...)		\  do {							\ -	kerror("I/O Error: " FMT, ##__VA_ARGS__);	\ +	pr_err("I/O Error: " FMT, ##__VA_ARGS__);	\  	fscache_io_error(&(___cache)->cache);		\  	set_bit(CACHEFILES_DEAD, &(___cache)->flags);	\  } while (0) @@ -307,8 +316,8 @@ do {							\  #define ASSERT(X)							\  do {									\  	if (unlikely(!(X))) {						\ -		printk(KERN_ERR "\n");					\ -		printk(KERN_ERR "CacheFiles: Assertion failed\n");	\ +		pr_err("\n");						\ +		pr_err("Assertion failed\n");		\  		BUG();							\  	}								\  } while (0) @@ -316,9 +325,9 @@ do {									\  #define ASSERTCMP(X, OP, Y)						\  do {									\  	if (unlikely(!((X) OP (Y)))) {					\ -		printk(KERN_ERR "\n");					\ -		printk(KERN_ERR "CacheFiles: Assertion failed\n");	\ -		printk(KERN_ERR "%lx " #OP " %lx is false\n",		\ +		pr_err("\n");						\ +		pr_err("Assertion failed\n");		\ +		pr_err("%lx " #OP " %lx is false\n",			\  		       (unsigned long)(X), (unsigned long)(Y));		\  		BUG();							\  	}								\ @@ -327,8 +336,8 @@ do {									\  #define ASSERTIF(C, X)							\  do {									\  	if (unlikely((C) && !(X))) {					\ -		printk(KERN_ERR "\n");					\ -		printk(KERN_ERR "CacheFiles: Assertion failed\n");	\ +		pr_err("\n");						\ +		pr_err("Assertion failed\n");		\  		BUG();							\  	}								\  } while (0) @@ -336,9 +345,9 @@ do {									\  #define ASSERTIFCMP(C, X, OP, Y)					\  do {									\  	if (unlikely((C) && !((X) OP (Y)))) {				\ -		printk(KERN_ERR "\n");					\ -		printk(KERN_ERR "CacheFiles: Assertion failed\n");	\ -		printk(KERN_ERR "%lx " #OP " %lx is false\n",		\ +		pr_err("\n");						\ +		pr_err("Assertion failed\n");		\ +		pr_err("%lx " #OP " %lx is false\n",			\  		       (unsigned long)(X), (unsigned long)(Y));		\  		BUG();							\  	}								\ diff --git a/fs/cachefiles/key.c b/fs/cachefiles/key.c index 81b8b2b3a67..33b58c60f2d 100644 --- a/fs/cachefiles/key.c +++ b/fs/cachefiles/key.c @@ -78,7 +78,7 @@ char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type)  	_debug("max: %d", max); -	key = kmalloc(max, GFP_KERNEL); +	key = kmalloc(max, cachefiles_gfp);  	if (!key)  		return NULL; diff --git a/fs/cachefiles/main.c b/fs/cachefiles/main.c index 4bfa8cf43bf..180edfb45f6 100644 --- a/fs/cachefiles/main.c +++ b/fs/cachefiles/main.c @@ -68,8 +68,7 @@ static int __init cachefiles_init(void)  				  SLAB_HWCACHE_ALIGN,  				  cachefiles_object_init_once);  	if (!cachefiles_object_jar) { -		printk(KERN_NOTICE -		       "CacheFiles: Failed to allocate an object jar\n"); +		pr_notice("Failed to allocate an object jar\n");  		goto error_object_jar;  	} @@ -77,7 +76,7 @@ static int __init cachefiles_init(void)  	if (ret < 0)  		goto error_proc; -	printk(KERN_INFO "CacheFiles: Loaded\n"); +	pr_info("Loaded\n");  	return 0;  error_proc: @@ -85,7 +84,7 @@ error_proc:  error_object_jar:  	misc_deregister(&cachefiles_dev);  error_dev: -	kerror("failed to register: %d", ret); +	pr_err("failed to register: %d", ret);  	return ret;  } @@ -96,7 +95,7 @@ fs_initcall(cachefiles_init);   */  static void __exit cachefiles_exit(void)  { -	printk(KERN_INFO "CacheFiles: Unloading\n"); +	pr_info("Unloading\n");  	cachefiles_proc_cleanup();  	kmem_cache_destroy(cachefiles_object_jar); diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 42c7fafc8bf..5bf2b41e66d 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c @@ -35,44 +35,42 @@ void __cachefiles_printk_object(struct cachefiles_object *object,  	struct fscache_cookie *cookie;  	unsigned keylen, loop; -	printk(KERN_ERR "%sobject: OBJ%x\n", -	       prefix, object->fscache.debug_id); -	printk(KERN_ERR "%sobjstate=%s fl=%lx wbusy=%x ev=%lx[%lx]\n", -	       prefix, fscache_object_states[object->fscache.state], +	pr_err("%sobject: OBJ%x\n", prefix, object->fscache.debug_id); +	pr_err("%sobjstate=%s fl=%lx wbusy=%x ev=%lx[%lx]\n", +	       prefix, object->fscache.state->name,  	       object->fscache.flags, work_busy(&object->fscache.work), -	       object->fscache.events, -	       object->fscache.event_mask & FSCACHE_OBJECT_EVENTS_MASK); -	printk(KERN_ERR "%sops=%u inp=%u exc=%u\n", +	       object->fscache.events, object->fscache.event_mask); +	pr_err("%sops=%u inp=%u exc=%u\n",  	       prefix, object->fscache.n_ops, object->fscache.n_in_progress,  	       object->fscache.n_exclusive); -	printk(KERN_ERR "%sparent=%p\n", +	pr_err("%sparent=%p\n",  	       prefix, object->fscache.parent);  	spin_lock(&object->fscache.lock);  	cookie = object->fscache.cookie;  	if (cookie) { -		printk(KERN_ERR "%scookie=%p [pr=%p nd=%p fl=%lx]\n", +		pr_err("%scookie=%p [pr=%p nd=%p fl=%lx]\n",  		       prefix,  		       object->fscache.cookie,  		       object->fscache.cookie->parent,  		       object->fscache.cookie->netfs_data,  		       object->fscache.cookie->flags); -		if (keybuf) +		if (keybuf && cookie->def)  			keylen = cookie->def->get_key(cookie->netfs_data, keybuf,  						      CACHEFILES_KEYBUF_SIZE);  		else  			keylen = 0;  	} else { -		printk(KERN_ERR "%scookie=NULL\n", prefix); +		pr_err("%scookie=NULL\n", prefix);  		keylen = 0;  	}  	spin_unlock(&object->fscache.lock);  	if (keylen) { -		printk(KERN_ERR "%skey=[%u] '", prefix, keylen); +		pr_err("%skey=[%u] '", prefix, keylen);  		for (loop = 0; loop < keylen; loop++) -			printk("%02x", keybuf[loop]); -		printk("'\n"); +			pr_cont("%02x", keybuf[loop]); +		pr_cont("'\n");  	}  } @@ -128,17 +126,15 @@ static void cachefiles_mark_object_buried(struct cachefiles_cache *cache,  found_dentry:  	kdebug("preemptive burial: OBJ%x [%s] %p",  	       object->fscache.debug_id, -	       fscache_object_states[object->fscache.state], +	       object->fscache.state->name,  	       dentry); -	if (object->fscache.state < FSCACHE_OBJECT_DYING) { -		printk(KERN_ERR "\n"); -		printk(KERN_ERR "CacheFiles: Error:" -		       " Can't preemptively bury live object\n"); +	if (fscache_object_is_live(&object->fscache)) { +		pr_err("\n"); +		pr_err("Error: Can't preemptively bury live object\n");  		cachefiles_printk_object(object, NULL);  	} else if (test_and_set_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) { -		printk(KERN_ERR "CacheFiles: Error:" -		       " Object already preemptively buried\n"); +		pr_err("Error: Object already preemptively buried\n");  	}  	write_unlock(&cache->active_lock); @@ -161,7 +157,7 @@ try_again:  	write_lock(&cache->active_lock);  	if (test_and_set_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)) { -		printk(KERN_ERR "CacheFiles: Error: Object already active\n"); +		pr_err("Error: Object already active\n");  		cachefiles_printk_object(object, NULL);  		BUG();  	} @@ -193,10 +189,9 @@ try_again:  	/* an old object from a previous incarnation is hogging the slot - we  	 * need to wait for it to be destroyed */  wait_for_old_object: -	if (xobject->fscache.state < FSCACHE_OBJECT_DYING) { -		printk(KERN_ERR "\n"); -		printk(KERN_ERR "CacheFiles: Error:" -		       " Unexpected object collision\n"); +	if (fscache_object_is_live(&object->fscache)) { +		pr_err("\n"); +		pr_err("Error: Unexpected object collision\n");  		cachefiles_printk_object(object, xobject);  		BUG();  	} @@ -242,9 +237,8 @@ wait_for_old_object:  		}  		if (timeout <= 0) { -			printk(KERN_ERR "\n"); -			printk(KERN_ERR "CacheFiles: Error: Overlong" -			       " wait for old active object to go away\n"); +			pr_err("\n"); +			pr_err("Error: Overlong wait for old active object to go away\n");  			cachefiles_printk_object(object, xobject);  			goto requeue;  		} @@ -275,6 +269,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,  				  bool preemptive)  {  	struct dentry *grave, *trap; +	struct path path, path_to_graveyard;  	char nbuffer[8 + 8 + 1];  	int ret; @@ -287,10 +282,18 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,  	/* non-directories can just be unlinked */  	if (!S_ISDIR(rep->d_inode->i_mode)) {  		_debug("unlink stale object"); -		ret = vfs_unlink(dir->d_inode, rep); -		if (preemptive) -			cachefiles_mark_object_buried(cache, rep); +		path.mnt = cache->mnt; +		path.dentry = dir; +		ret = security_path_unlink(&path, rep); +		if (ret < 0) { +			cachefiles_io_error(cache, "Unlink security error"); +		} else { +			ret = vfs_unlink(dir->d_inode, rep, NULL); + +			if (preemptive) +				cachefiles_mark_object_buried(cache, rep); +		}  		mutex_unlock(&dir->d_inode->i_mutex); @@ -379,12 +382,23 @@ try_again:  	}  	/* attempt the rename */ -	ret = vfs_rename(dir->d_inode, rep, cache->graveyard->d_inode, grave); -	if (ret != 0 && ret != -ENOMEM) -		cachefiles_io_error(cache, "Rename failed with error %d", ret); +	path.mnt = cache->mnt; +	path.dentry = dir; +	path_to_graveyard.mnt = cache->mnt; +	path_to_graveyard.dentry = cache->graveyard; +	ret = security_path_rename(&path, rep, &path_to_graveyard, grave, 0); +	if (ret < 0) { +		cachefiles_io_error(cache, "Rename security error %d", ret); +	} else { +		ret = vfs_rename(dir->d_inode, rep, +				 cache->graveyard->d_inode, grave, NULL, 0); +		if (ret != 0 && ret != -ENOMEM) +			cachefiles_io_error(cache, +					    "Rename failed with error %d", ret); -	if (preemptive) -		cachefiles_mark_object_buried(cache, rep); +		if (preemptive) +			cachefiles_mark_object_buried(cache, rep); +	}  	unlock_rename(cache->graveyard, dir);  	dput(grave); @@ -448,6 +462,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,  {  	struct cachefiles_cache *cache;  	struct dentry *dir, *next = NULL; +	struct path path;  	unsigned long start;  	const char *name;  	int ret, nlen; @@ -458,6 +473,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,  	cache = container_of(parent->fscache.cache,  			     struct cachefiles_cache, cache); +	path.mnt = cache->mnt;  	ASSERT(parent->dentry);  	ASSERT(parent->dentry->d_inode); @@ -511,6 +527,10 @@ lookup_again:  			if (ret < 0)  				goto create_error; +			path.dentry = dir; +			ret = security_path_mkdir(&path, next, 0); +			if (ret < 0) +				goto create_error;  			start = jiffies;  			ret = vfs_mkdir(dir->d_inode, next, 0);  			cachefiles_hist(cachefiles_mkdir_histogram, start); @@ -523,7 +543,7 @@ lookup_again:  			       next, next->d_inode, next->d_inode->i_ino);  		} else if (!S_ISDIR(next->d_inode->i_mode)) { -			kerror("inode %lu is not a directory", +			pr_err("inode %lu is not a directory",  			       next->d_inode->i_ino);  			ret = -ENOBUFS;  			goto error; @@ -536,8 +556,12 @@ lookup_again:  			if (ret < 0)  				goto create_error; +			path.dentry = dir; +			ret = security_path_mknod(&path, next, S_IFREG, 0); +			if (ret < 0) +				goto create_error;  			start = jiffies; -			ret = vfs_create(dir->d_inode, next, S_IFREG, NULL); +			ret = vfs_create(dir->d_inode, next, S_IFREG, true);  			cachefiles_hist(cachefiles_create_histogram, start);  			if (ret < 0)  				goto create_error; @@ -550,7 +574,7 @@ lookup_again:  		} else if (!S_ISDIR(next->d_inode->i_mode) &&  			   !S_ISREG(next->d_inode->i_mode)  			   ) { -			kerror("inode %lu is not a file or directory", +			pr_err("inode %lu is not a file or directory",  			       next->d_inode->i_ino);  			ret = -ENOBUFS;  			goto error; @@ -616,7 +640,8 @@ lookup_again:  		 * (this is used to keep track of culling, and atimes are only  		 * updated by read, write and readdir but not lookup or  		 * open) */ -		touch_atime(cache->mnt, next); +		path.dentry = next; +		touch_atime(&path);  	}  	/* open a file interface onto a data file */ @@ -692,6 +717,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,  {  	struct dentry *subdir;  	unsigned long start; +	struct path path;  	int ret;  	_enter(",,%s", dirname); @@ -719,6 +745,11 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,  		_debug("attempt mkdir"); +		path.mnt = cache->mnt; +		path.dentry = dir; +		ret = security_path_mkdir(&path, subdir, 0700); +		if (ret < 0) +			goto mkdir_error;  		ret = vfs_mkdir(dir->d_inode, subdir, 0700);  		if (ret < 0)  			goto mkdir_error; @@ -737,14 +768,13 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,  	ASSERT(subdir->d_inode);  	if (!S_ISDIR(subdir->d_inode->i_mode)) { -		kerror("%s is not a directory", dirname); +		pr_err("%s is not a directory", dirname);  		ret = -EIO;  		goto check_error;  	}  	ret = -EPERM; -	if (!subdir->d_inode->i_op || -	    !subdir->d_inode->i_op->setxattr || +	if (!subdir->d_inode->i_op->setxattr ||  	    !subdir->d_inode->i_op->getxattr ||  	    !subdir->d_inode->i_op->lookup ||  	    !subdir->d_inode->i_op->mkdir || @@ -765,13 +795,13 @@ check_error:  mkdir_error:  	mutex_unlock(&dir->d_inode->i_mutex);  	dput(subdir); -	kerror("mkdir %s failed with error %d", dirname, ret); +	pr_err("mkdir %s failed with error %d", dirname, ret);  	return ERR_PTR(ret);  lookup_error:  	mutex_unlock(&dir->d_inode->i_mutex);  	ret = PTR_ERR(subdir); -	kerror("Lookup %s failed with error %d", dirname, ret); +	pr_err("Lookup %s failed with error %d", dirname, ret);  	return ERR_PTR(ret);  nomem_d_alloc: @@ -800,7 +830,7 @@ static struct dentry *cachefiles_check_active(struct cachefiles_cache *cache,  	//       dir->d_name.len, dir->d_name.len, dir->d_name.name, filename);  	/* look up the victim */ -	mutex_lock_nested(&dir->d_inode->i_mutex, 1); +	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);  	start = jiffies;  	victim = lookup_one_len(filename, dir, strlen(filename)); @@ -861,7 +891,7 @@ lookup_error:  	if (ret == -EIO) {  		cachefiles_io_error(cache, "Lookup failed");  	} else if (ret != -ENOMEM) { -		kerror("Internal error: %d", ret); +		pr_err("Internal error: %d", ret);  		ret = -EIO;  	} @@ -920,7 +950,7 @@ error:  	}  	if (ret != -ENOMEM) { -		kerror("Internal error: %d", ret); +		pr_err("Internal error: %d", ret);  		ret = -EIO;  	} diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c index 0e3c0924cc3..4b1fb5ca65b 100644 --- a/fs/cachefiles/rdwr.c +++ b/fs/cachefiles/rdwr.c @@ -12,6 +12,7 @@  #include <linux/mount.h>  #include <linux/slab.h>  #include <linux/file.h> +#include <linux/swap.h>  #include "internal.h"  /* @@ -77,25 +78,25 @@ static int cachefiles_read_reissue(struct cachefiles_object *object,  	struct page *backpage = monitor->back_page, *backpage2;  	int ret; -	kenter("{ino=%lx},{%lx,%lx}", +	_enter("{ino=%lx},{%lx,%lx}",  	       object->backer->d_inode->i_ino,  	       backpage->index, backpage->flags);  	/* skip if the page was truncated away completely */  	if (backpage->mapping != bmapping) { -		kleave(" = -ENODATA [mapping]"); +		_leave(" = -ENODATA [mapping]");  		return -ENODATA;  	}  	backpage2 = find_get_page(bmapping, backpage->index);  	if (!backpage2) { -		kleave(" = -ENODATA [gone]"); +		_leave(" = -ENODATA [gone]");  		return -ENODATA;  	}  	if (backpage != backpage2) {  		put_page(backpage2); -		kleave(" = -ENODATA [different]"); +		_leave(" = -ENODATA [different]");  		return -ENODATA;  	} @@ -114,7 +115,7 @@ static int cachefiles_read_reissue(struct cachefiles_object *object,  		if (PageUptodate(backpage))  			goto unlock_discard; -		kdebug("reissue read"); +		_debug("reissue read");  		ret = bmapping->a_ops->readpage(NULL, backpage);  		if (ret < 0)  			goto unlock_discard; @@ -129,7 +130,7 @@ static int cachefiles_read_reissue(struct cachefiles_object *object,  	}  	/* it'll reappear on the todo list */ -	kleave(" = -EINPROGRESS"); +	_leave(" = -EINPROGRESS");  	return -EINPROGRESS;  unlock_discard: @@ -137,7 +138,7 @@ unlock_discard:  	spin_lock_irq(&object->work_lock);  	list_del(&monitor->op_link);  	spin_unlock_irq(&object->work_lock); -	kleave(" = %d", ret); +	_leave(" = %d", ret);  	return ret;  } @@ -174,11 +175,13 @@ static void cachefiles_read_copier(struct fscache_operation *_op)  		_debug("- copy {%lu}", monitor->back_page->index);  	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); - -			pagevec_add(&pagevec, monitor->netfs_page); -			fscache_mark_pages_cached(monitor->op, &pagevec); +			fscache_mark_page_cached(monitor->op, +						 monitor->netfs_page);  			error = 0;  		} else if (!PageError(monitor->back_page)) {  			/* the page has probably been truncated */ @@ -198,6 +201,7 @@ static void cachefiles_read_copier(struct fscache_operation *_op)  		fscache_end_io(op, monitor->netfs_page, error);  		page_cache_release(monitor->netfs_page); +		fscache_retrieval_complete(op, 1);  		fscache_put_retrieval(op);  		kfree(monitor); @@ -224,8 +228,7 @@ static void cachefiles_read_copier(struct fscache_operation *_op)   */  static int cachefiles_read_backing_file_one(struct cachefiles_object *object,  					    struct fscache_retrieval *op, -					    struct page *netpage, -					    struct pagevec *pagevec) +					    struct page *netpage)  {  	struct cachefiles_one_read *monitor;  	struct address_space *bmapping; @@ -234,12 +237,10 @@ static int cachefiles_read_backing_file_one(struct cachefiles_object *object,  	_enter(""); -	pagevec_reinit(pagevec); -  	_debug("read back %p{%lu,%d}",  	       netpage, netpage->index, page_count(netpage)); -	monitor = kzalloc(sizeof(*monitor), GFP_KERNEL); +	monitor = kzalloc(sizeof(*monitor), cachefiles_gfp);  	if (!monitor)  		goto nomem; @@ -258,31 +259,28 @@ static int cachefiles_read_backing_file_one(struct cachefiles_object *object,  			goto backing_page_already_present;  		if (!newpage) { -			newpage = page_cache_alloc_cold(bmapping); +			newpage = __page_cache_alloc(cachefiles_gfp | +						     __GFP_COLD);  			if (!newpage)  				goto nomem_monitor;  		} -		ret = add_to_page_cache(newpage, bmapping, -					netpage->index, GFP_KERNEL); +		ret = add_to_page_cache_lru(newpage, bmapping, +					    netpage->index, cachefiles_gfp);  		if (ret == 0)  			goto installed_new_backing_page;  		if (ret != -EEXIST)  			goto nomem_page;  	} -	/* we've installed a new backing page, so now we need to add it -	 * to the LRU list and start it reading */ +	/* we've installed a new backing page, so now we need to start +	 * it reading */  installed_new_backing_page:  	_debug("- new %p", newpage);  	backpage = newpage;  	newpage = NULL; -	page_cache_get(backpage); -	pagevec_add(pagevec, backpage); -	__pagevec_lru_add_file(pagevec); -  read_backing_page:  	ret = bmapping->a_ops->readpage(NULL, backpage);  	if (ret < 0) @@ -335,11 +333,11 @@ backing_page_already_present:  backing_page_already_uptodate:  	_debug("- uptodate"); -	pagevec_add(pagevec, netpage); -	fscache_mark_pages_cached(op, pagevec); +	fscache_mark_page_cached(op, netpage);  	copy_highpage(netpage, backpage);  	fscache_end_io(op, netpage, 0); +	fscache_retrieval_complete(op, 1);  success:  	_debug("success"); @@ -357,10 +355,13 @@ out:  read_error:  	_debug("read error %d", ret); -	if (ret == -ENOMEM) +	if (ret == -ENOMEM) { +		fscache_retrieval_complete(op, 1);  		goto out; +	}  io_error:  	cachefiles_io_error_obj(object, "Page read error on backing file"); +	fscache_retrieval_complete(op, 1);  	ret = -ENOBUFS;  	goto out; @@ -370,6 +371,7 @@ nomem_monitor:  	fscache_put_retrieval(monitor->op);  	kfree(monitor);  nomem: +	fscache_retrieval_complete(op, 1);  	_leave(" = -ENOMEM");  	return -ENOMEM;  } @@ -408,7 +410,7 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,  	_enter("{%p},{%lx},,,", object, page->index);  	if (!object->backer) -		return -ENOBUFS; +		goto enobufs;  	inode = object->backer->d_inode;  	ASSERT(S_ISREG(inode->i_mode)); @@ -417,7 +419,7 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,  	/* calculate the shift required to use bmap */  	if (inode->i_sb->s_blocksize > PAGE_SIZE) -		return -ENOBUFS; +		goto enobufs;  	shift = PAGE_SHIFT - inode->i_sb->s_blocksize_bits; @@ -444,19 +446,23 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,  	if (block) {  		/* submit the apparently valid page to the backing fs to be  		 * read from disk */ -		ret = cachefiles_read_backing_file_one(object, op, page, -						       &pagevec); +		ret = cachefiles_read_backing_file_one(object, op, page);  	} else if (cachefiles_has_space(cache, 0, 1) == 0) {  		/* there's space in the cache we can use */ -		pagevec_add(&pagevec, page); -		fscache_mark_pages_cached(op, &pagevec); +		fscache_mark_page_cached(op, page); +		fscache_retrieval_complete(op, 1);  		ret = -ENODATA;  	} else { -		ret = -ENOBUFS; +		goto enobufs;  	}  	_leave(" = %d", ret);  	return ret; + +enobufs: +	fscache_retrieval_complete(op, 1); +	_leave(" = -ENOBUFS"); +	return -ENOBUFS;  }  /* @@ -465,19 +471,15 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,   */  static int cachefiles_read_backing_file(struct cachefiles_object *object,  					struct fscache_retrieval *op, -					struct list_head *list, -					struct pagevec *mark_pvec) +					struct list_head *list)  {  	struct cachefiles_one_read *monitor = NULL;  	struct address_space *bmapping = object->backer->d_inode->i_mapping; -	struct pagevec lru_pvec;  	struct page *newpage = NULL, *netpage, *_n, *backpage = NULL;  	int ret = 0;  	_enter(""); -	pagevec_init(&lru_pvec, 0); -  	list_for_each_entry_safe(netpage, _n, list, lru) {  		list_del(&netpage->lru); @@ -485,7 +487,7 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,  		       netpage, netpage->index, page_count(netpage));  		if (!monitor) { -			monitor = kzalloc(sizeof(*monitor), GFP_KERNEL); +			monitor = kzalloc(sizeof(*monitor), cachefiles_gfp);  			if (!monitor)  				goto nomem; @@ -500,31 +502,29 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,  				goto backing_page_already_present;  			if (!newpage) { -				newpage = page_cache_alloc_cold(bmapping); +				newpage = __page_cache_alloc(cachefiles_gfp | +							     __GFP_COLD);  				if (!newpage)  					goto nomem;  			} -			ret = add_to_page_cache(newpage, bmapping, -						netpage->index, GFP_KERNEL); +			ret = add_to_page_cache_lru(newpage, bmapping, +						    netpage->index, +						    cachefiles_gfp);  			if (ret == 0)  				goto installed_new_backing_page;  			if (ret != -EEXIST)  				goto nomem;  		} -		/* we've installed a new backing page, so now we need to add it -		 * to the LRU list and start it reading */ +		/* we've installed a new backing page, so now we need +		 * to start it reading */  	installed_new_backing_page:  		_debug("- new %p", newpage);  		backpage = newpage;  		newpage = NULL; -		page_cache_get(backpage); -		if (!pagevec_add(&lru_pvec, backpage)) -			__pagevec_lru_add_file(&lru_pvec); -  	reread_backing_page:  		ret = bmapping->a_ops->readpage(NULL, backpage);  		if (ret < 0) @@ -535,20 +535,17 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,  	monitor_backing_page:  		_debug("- monitor add"); -		ret = add_to_page_cache(netpage, op->mapping, netpage->index, -					GFP_KERNEL); +		ret = add_to_page_cache_lru(netpage, op->mapping, +					    netpage->index, cachefiles_gfp);  		if (ret < 0) {  			if (ret == -EEXIST) {  				page_cache_release(netpage); +				fscache_retrieval_complete(op, 1);  				continue;  			}  			goto nomem;  		} -		page_cache_get(netpage); -		if (!pagevec_add(&lru_pvec, netpage)) -			__pagevec_lru_add_file(&lru_pvec); -  		/* install a monitor */  		page_cache_get(netpage);  		monitor->netfs_page = netpage; @@ -611,11 +608,12 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,  	backing_page_already_uptodate:  		_debug("- uptodate"); -		ret = add_to_page_cache(netpage, op->mapping, netpage->index, -					GFP_KERNEL); +		ret = add_to_page_cache_lru(netpage, op->mapping, +					    netpage->index, cachefiles_gfp);  		if (ret < 0) {  			if (ret == -EEXIST) {  				page_cache_release(netpage); +				fscache_retrieval_complete(op, 1);  				continue;  			}  			goto nomem; @@ -626,16 +624,13 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,  		page_cache_release(backpage);  		backpage = NULL; -		if (!pagevec_add(mark_pvec, netpage)) -			fscache_mark_pages_cached(op, mark_pvec); - -		page_cache_get(netpage); -		if (!pagevec_add(&lru_pvec, netpage)) -			__pagevec_lru_add_file(&lru_pvec); +		fscache_mark_page_cached(op, netpage); +		/* the netpage is unlocked and marked up to date here */  		fscache_end_io(op, netpage, 0);  		page_cache_release(netpage);  		netpage = NULL; +		fscache_retrieval_complete(op, 1);  		continue;  	} @@ -645,8 +640,6 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,  out:  	/* tidy up */ -	pagevec_lru_add_file(&lru_pvec); -  	if (newpage)  		page_cache_release(newpage);  	if (netpage) @@ -661,6 +654,7 @@ out:  	list_for_each_entry_safe(netpage, _n, list, lru) {  		list_del(&netpage->lru);  		page_cache_release(netpage); +		fscache_retrieval_complete(op, 1);  	}  	_leave(" = %d", ret); @@ -669,15 +663,17 @@ out:  nomem:  	_debug("nomem");  	ret = -ENOMEM; -	goto out; +	goto record_page_complete;  read_error:  	_debug("read error %d", ret);  	if (ret == -ENOMEM) -		goto out; +		goto record_page_complete;  io_error:  	cachefiles_io_error_obj(object, "Page read error on backing file");  	ret = -ENOBUFS; +record_page_complete: +	fscache_retrieval_complete(op, 1);  	goto out;  } @@ -709,7 +705,7 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,  	       *nr_pages);  	if (!object->backer) -		return -ENOBUFS; +		goto all_enobufs;  	space = 1;  	if (cachefiles_has_space(cache, 0, *nr_pages) < 0) @@ -722,7 +718,7 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,  	/* calculate the shift required to use bmap */  	if (inode->i_sb->s_blocksize > PAGE_SIZE) -		return -ENOBUFS; +		goto all_enobufs;  	shift = PAGE_SHIFT - inode->i_sb->s_blocksize_bits; @@ -762,7 +758,10 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,  			nrbackpages++;  		} else if (space && pagevec_add(&pagevec, page) == 0) {  			fscache_mark_pages_cached(op, &pagevec); +			fscache_retrieval_complete(op, 1);  			ret = -ENODATA; +		} else { +			fscache_retrieval_complete(op, 1);  		}  	} @@ -775,18 +774,18 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,  	/* submit the apparently valid pages to the backing fs to be read from  	 * disk */  	if (nrbackpages > 0) { -		ret2 = cachefiles_read_backing_file(object, op, &backpages, -						    &pagevec); +		ret2 = cachefiles_read_backing_file(object, op, &backpages);  		if (ret2 == -ENOMEM || ret2 == -EINTR)  			ret = ret2;  	} -	if (pagevec_count(&pagevec) > 0) -		fscache_mark_pages_cached(op, &pagevec); -  	_leave(" = %d [nr=%u%s]",  	       ret, *nr_pages, list_empty(pages) ? " empty" : "");  	return ret; + +all_enobufs: +	fscache_retrieval_complete(op, *nr_pages); +	return -ENOBUFS;  }  /* @@ -806,7 +805,6 @@ int cachefiles_allocate_page(struct fscache_retrieval *op,  {  	struct cachefiles_object *object;  	struct cachefiles_cache *cache; -	struct pagevec pagevec;  	int ret;  	object = container_of(op->op.object, @@ -817,14 +815,12 @@ int cachefiles_allocate_page(struct fscache_retrieval *op,  	_enter("%p,{%lx},", object, page->index);  	ret = cachefiles_has_space(cache, 0, 1); -	if (ret == 0) { -		pagevec_init(&pagevec, 0); -		pagevec_add(&pagevec, page); -		fscache_mark_pages_cached(op, &pagevec); -	} else { +	if (ret == 0) +		fscache_mark_page_cached(op, page); +	else  		ret = -ENOBUFS; -	} +	fscache_retrieval_complete(op, 1);  	_leave(" = %d", ret);  	return ret;  } @@ -874,6 +870,7 @@ int cachefiles_allocate_pages(struct fscache_retrieval *op,  		ret = -ENOBUFS;  	} +	fscache_retrieval_complete(op, *nr_pages);  	_leave(" = %d", ret);  	return ret;  } @@ -891,6 +888,7 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page)  	struct cachefiles_cache *cache;  	mm_segment_t old_fs;  	struct file *file; +	struct path path;  	loff_t pos, eof;  	size_t len;  	void *data; @@ -916,10 +914,9 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page)  	/* write the page to the backing filesystem and let it store it in its  	 * own time */ -	dget(object->backer); -	mntget(cache->mnt); -	file = dentry_open(object->backer, cache->mnt, O_RDWR, -			   cache->cache_cred); +	path.mnt = cache->mnt; +	path.dentry = object->backer; +	file = dentry_open(&path, O_RDWR | O_LARGEFILE, cache->cache_cred);  	if (IS_ERR(file)) {  		ret = PTR_ERR(file);  	} else { @@ -942,12 +939,14 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page)  			}  			data = kmap(page); +			file_start_write(file);  			old_fs = get_fs();  			set_fs(KERNEL_DS);  			ret = file->f_op->write(  				file, (const void __user *) data, len, &pos);  			set_fs(old_fs);  			kunmap(page); +			file_end_write(file);  			if (ret != len)  				ret = -EIO;  		} diff --git a/fs/cachefiles/security.c b/fs/cachefiles/security.c index 039b5011d83..396c18ea276 100644 --- a/fs/cachefiles/security.c +++ b/fs/cachefiles/security.c @@ -34,9 +34,7 @@ int cachefiles_get_security_ID(struct cachefiles_cache *cache)  		ret = set_security_override_from_ctx(new, cache->secctx);  		if (ret < 0) {  			put_cred(new); -			printk(KERN_ERR "CacheFiles:" -			       " Security denies permission to nominate" -			       " security context: error %d\n", +			pr_err("Security denies permission to nominate security context: error %d\n",  			       ret);  			goto error;  		} @@ -59,16 +57,14 @@ static int cachefiles_check_cache_dir(struct cachefiles_cache *cache,  	ret = security_inode_mkdir(root->d_inode, root, 0);  	if (ret < 0) { -		printk(KERN_ERR "CacheFiles:" -		       " Security denies permission to make dirs: error %d", +		pr_err("Security denies permission to make dirs: error %d",  		       ret);  		return ret;  	}  	ret = security_inode_create(root->d_inode, root, 0);  	if (ret < 0) -		printk(KERN_ERR "CacheFiles:" -		       " Security denies permission to create files: error %d", +		pr_err("Security denies permission to create files: error %d",  		       ret);  	return ret; diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c index e18b183b47e..1ad51ffbb27 100644 --- a/fs/cachefiles/xattr.c +++ b/fs/cachefiles/xattr.c @@ -51,7 +51,7 @@ int cachefiles_check_object_type(struct cachefiles_object *object)  	}  	if (ret != -EEXIST) { -		kerror("Can't set xattr on %*.*s [%lu] (err %d)", +		pr_err("Can't set xattr on %*.*s [%lu] (err %d)",  		       dentry->d_name.len, dentry->d_name.len,  		       dentry->d_name.name, dentry->d_inode->i_ino,  		       -ret); @@ -64,7 +64,7 @@ int cachefiles_check_object_type(struct cachefiles_object *object)  		if (ret == -ERANGE)  			goto bad_type_length; -		kerror("Can't read xattr on %*.*s [%lu] (err %d)", +		pr_err("Can't read xattr on %*.*s [%lu] (err %d)",  		       dentry->d_name.len, dentry->d_name.len,  		       dentry->d_name.name, dentry->d_inode->i_ino,  		       -ret); @@ -85,14 +85,14 @@ error:  	return ret;  bad_type_length: -	kerror("Cache object %lu type xattr length incorrect", +	pr_err("Cache object %lu type xattr length incorrect",  	       dentry->d_inode->i_ino);  	ret = -EIO;  	goto error;  bad_type:  	xtype[2] = 0; -	kerror("Cache object %*.*s [%lu] type %s not %s", +	pr_err("Cache object %*.*s [%lu] type %s not %s",  	       dentry->d_name.len, dentry->d_name.len,  	       dentry->d_name.name, dentry->d_inode->i_ino,  	       xtype, type); @@ -109,13 +109,12 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object,  	struct dentry *dentry = object->dentry;  	int ret; -	ASSERT(object->fscache.cookie);  	ASSERT(dentry);  	_enter("%p,#%d", object, auxdata->len);  	/* attempt to install the cache metadata directly */ -	_debug("SET %s #%u", object->fscache.cookie->def->name, auxdata->len); +	_debug("SET #%u", auxdata->len);  	ret = vfs_setxattr(dentry, cachefiles_xattr_cache,  			   &auxdata->type, auxdata->len, @@ -138,13 +137,12 @@ int cachefiles_update_object_xattr(struct cachefiles_object *object,  	struct dentry *dentry = object->dentry;  	int ret; -	ASSERT(object->fscache.cookie);  	ASSERT(dentry);  	_enter("%p,#%d", object, auxdata->len);  	/* attempt to install the cache metadata directly */ -	_debug("SET %s #%u", object->fscache.cookie->def->name, auxdata->len); +	_debug("SET #%u", auxdata->len);  	ret = vfs_setxattr(dentry, cachefiles_xattr_cache,  			   &auxdata->type, auxdata->len, @@ -159,6 +157,43 @@ int cachefiles_update_object_xattr(struct cachefiles_object *object,  }  /* + * check the consistency between the backing cache and the FS-Cache cookie + */ +int cachefiles_check_auxdata(struct cachefiles_object *object) +{ +	struct cachefiles_xattr *auxbuf; +	enum fscache_checkaux validity; +	struct dentry *dentry = object->dentry; +	ssize_t xlen; +	int ret; + +	ASSERT(dentry); +	ASSERT(dentry->d_inode); +	ASSERT(object->fscache.cookie->def->check_aux); + +	auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, GFP_KERNEL); +	if (!auxbuf) +		return -ENOMEM; + +	xlen = vfs_getxattr(dentry, cachefiles_xattr_cache, +			    &auxbuf->type, 512 + 1); +	ret = -ESTALE; +	if (xlen < 1 || +	    auxbuf->type != object->fscache.cookie->def->type) +		goto error; + +	xlen--; +	validity = fscache_check_aux(&object->fscache, &auxbuf->data, xlen); +	if (validity != FSCACHE_CHECKAUX_OKAY) +		goto error; + +	ret = 0; +error: +	kfree(auxbuf); +	return ret; +} + +/*   * check the state xattr on a cache file   * - return -ESTALE if the object should be deleted   */ @@ -174,7 +209,7 @@ int cachefiles_check_object_xattr(struct cachefiles_object *object,  	ASSERT(dentry);  	ASSERT(dentry->d_inode); -	auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, GFP_KERNEL); +	auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, cachefiles_gfp);  	if (!auxbuf) {  		_leave(" = -ENOMEM");  		return -ENOMEM; @@ -258,7 +293,7 @@ error:  	return ret;  bad_type_length: -	kerror("Cache object %lu xattr length incorrect", +	pr_err("Cache object %lu xattr length incorrect",  	       dentry->d_inode->i_ino);  	ret = -EIO;  	goto error;  | 
