cachefiles: Use path structs in cachefiles_cache struct

Use path structs in struct cachefiles_cache to represent significant
directories rather than assembling them on the fly.

Signed-off-by: David Howells <dhowells@redhat.com>
diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c
index 9bfa8ef..f0054c7 100644
--- a/fs/cachefiles/bind.c
+++ b/fs/cachefiles/bind.c
@@ -72,9 +72,8 @@ int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args)
 static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
 {
 	struct fscache_cache *fscache;
-	struct path path;
 	struct kstatfs stats;
-	struct dentry *graveyard, *cachedir, *root;
+	struct dentry *root;
 	const struct cred *saved_cred;
 	int ret;
 
@@ -100,20 +99,18 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
 	cachefiles_begin_secure(cache, &saved_cred);
 
 	/* look up the directory at the root of the cache */
-	ret = kern_path(cache->rootdirname, LOOKUP_DIRECTORY, &path);
+	ret = kern_path(cache->rootdirname, LOOKUP_DIRECTORY, &cache->root_path);
 	if (ret < 0)
 		goto error_open_root;
 
-	cache->path.mnt = path.mnt;
-	root = path.dentry;
-
 	ret = -EINVAL;
-	if (mnt_user_ns(path.mnt) != &init_user_ns) {
+	if (mnt_user_ns(cache->root_path.mnt) != &init_user_ns) {
 		pr_warn("File cache on idmapped mounts not supported");
 		goto error_unsupported;
 	}
 
 	/* check parameters */
+	root = cache->root_path.dentry;
 	ret = -EOPNOTSUPP;
 	if (d_is_negative(root) ||
 	    !d_backing_inode(root)->i_op->lookup ||
@@ -134,7 +131,7 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
 		goto error_unsupported;
 
 	/* get the cache size and blocksize */
-	ret = vfs_statfs(&path, &stats);
+	ret = vfs_statfs(&cache->root_path, &stats);
 	if (ret < 0)
 		goto error_unsupported;
 
@@ -180,32 +177,21 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
 	       (unsigned long long) cache->bcull,
 	       (unsigned long long) cache->bstop);
 
-	/* get the cache directory and check its type */
-	cachedir = cachefiles_get_directory(cache, root, "cache");
-	if (IS_ERR(cachedir)) {
-		ret = PTR_ERR(cachedir);
+	ret = cachefiles_get_directory(cache, "cache", &cache->cache_path);
+	if (ret < 0)
 		goto error_unsupported;
-	}
 
-	cache->path.dentry = cachedir;
-
-	/* get the graveyard directory */
-	graveyard = cachefiles_get_directory(cache, root, "graveyard");
-	if (IS_ERR(graveyard)) {
-		ret = PTR_ERR(graveyard);
+	ret = cachefiles_get_directory(cache, "graveyard", &cache->graveyard_path);
+	if (ret < 0)
 		goto error_unsupported;
-	}
 
-	cache->graveyard = graveyard;
 	cache->cache = fscache;
-
 	ret = fscache_add_cache(fscache, &cachefiles_cache_ops, cache);
 	if (ret < 0)
 		goto error_add_cache;
 
 	/* done */
 	set_bit(CACHEFILES_READY, &cache->flags);
-	dput(root);
 
 	pr_info("File cache on %s registered\n", fscache->name);
 
@@ -216,13 +202,13 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
 	return 0;
 
 error_add_cache:
-	dput(cache->graveyard);
-	cache->graveyard = NULL;
+	path_put(&cache->graveyard_path);
+	memset(&cache->graveyard_path, 0, sizeof(cache->graveyard_path));
 error_unsupported:
-	path_put(&cache->path);
-	cache->path.dentry = NULL;
-	cache->path.mnt = NULL;
-	dput(root);
+	path_put(&cache->cache_path);
+	path_put(&cache->root_path);
+	memset(&cache->cache_path, 0, sizeof(cache->cache_path));
+	memset(&cache->root_path, 0, sizeof(cache->root_path));
 error_open_root:
 	cachefiles_end_secure(cache, saved_cred);
 error_getsec:
@@ -405,8 +391,9 @@ void cachefiles_daemon_unbind(struct cachefiles_cache *cache)
 	if (test_bit(CACHEFILES_READY, &cache->flags))
 		cachefiles_withdraw_cache(cache);
 
-	dput(cache->graveyard);
-	path_put(&cache->path);
+	path_put(&cache->graveyard_path);
+	path_put(&cache->cache_path);
+	path_put(&cache->root_path);
 
 	kfree(cache->rootdirname);
 	kfree(cache->secctx);
diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c
index 75a7c7f..e402018 100644
--- a/fs/cachefiles/daemon.c
+++ b/fs/cachefiles/daemon.c
@@ -685,7 +685,7 @@ int cachefiles_has_space(struct cachefiles_cache *cache,
 	/* find out how many pages of blockdev are available */
 	memset(&stats, 0, sizeof(stats));
 
-	ret = vfs_statfs(&cache->path, &stats);
+	ret = vfs_statfs(&cache->root_path, &stats);
 	if (ret < 0) {
 		if (ret == -EIO)
 			cachefiles_io_error(cache, "statfs failed");
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c
index b67919f..153f0cc 100644
--- a/fs/cachefiles/interface.c
+++ b/fs/cachefiles/interface.c
@@ -197,7 +197,7 @@ static bool cachefiles_shorten_object(struct cachefiles_object *object, loff_t n
 	dio_size = round_up(new_size, CACHEFILES_DIO_BLOCK_SIZE);
 	i_size = i_size_read(inode);
 
-	path.mnt = cache->path.mnt;
+	path.mnt = cache->cache_path.mnt;
 	path.dentry = object->dentry;
 
 	trace_cachefiles_trunc(object, inode, i_size, dio_size, cachefiles_trunc_shrink);
@@ -404,9 +404,9 @@ void cachefiles_sync_cache(struct cachefiles_cache *cache)
 	/* make sure all pages pinned by operations on behalf of the netfs are
 	 * written to disc */
 	cachefiles_begin_secure(cache, &saved_cred);
-	down_read(&cache->path.mnt->mnt_sb->s_umount);
-	ret = sync_filesystem(cache->path.mnt->mnt_sb);
-	up_read(&cache->path.mnt->mnt_sb->s_umount);
+	down_read(&cache->cache_path.mnt->mnt_sb->s_umount);
+	ret = sync_filesystem(cache->cache_path.mnt->mnt_sb);
+	up_read(&cache->cache_path.mnt->mnt_sb->s_umount);
 	cachefiles_end_secure(cache, saved_cred);
 
 	if (ret == -EIO)
@@ -497,8 +497,9 @@ static struct file *cachefiles_create_tmpfile(struct cachefiles_object *object)
 
 	cachefiles_begin_secure(cache, &saved_cred);
 
-	path.mnt = cache->path.mnt;
-	path.dentry = vfs_tmpfile(&init_user_ns, cache->graveyard, S_IFREG, O_RDWR);
+	path.mnt = cache->cache_path.mnt;
+	path.dentry = vfs_tmpfile(&init_user_ns, cache->graveyard_path.dentry,
+				  S_IFREG, O_RDWR);
 	if (IS_ERR(path.dentry)) {
 		if (PTR_ERR(path.dentry) == -EIO)
 			cachefiles_io_error_obj(object, "Failed to create tmpfile");
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
index ab91d15..4b09864 100644
--- a/fs/cachefiles/internal.h
+++ b/fs/cachefiles/internal.h
@@ -94,8 +94,9 @@ extern struct kmem_cache *cachefiles_object_jar;
  */
 struct cachefiles_cache {
 	struct fscache_cache		*cache;		/* Cache cookie */
-	struct path			path;		/* Path to the cache */
-	struct dentry			*graveyard;	/* directory into which dead objects go */
+	struct path			root_path;	/* Path to the cache */
+	struct path			cache_path;	/* Path to the cache */
+	struct path			graveyard_path;	/* directory into which dead objects go */
 	struct file			*cachefilesd;	/* manager daemon handle */
 	struct list_head		object_list;	/* List of active objects */
 	struct list_head		withdrawal_list; /* List of objects to be withdrawn */
@@ -215,9 +216,9 @@ extern int cachefiles_delete_object(struct cachefiles_cache *cache,
 				    struct cachefiles_object *object);
 extern bool cachefiles_walk_to_object(struct cachefiles_object *object,
 				      const char *key);
-extern struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
-					       struct dentry *dir,
-					       const char *name);
+extern int cachefiles_get_directory(struct cachefiles_cache *cache,
+				    const char *name,
+				    struct path *_path);
 
 extern int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
 			   char *filename);
diff --git a/fs/cachefiles/io.c b/fs/cachefiles/io.c
index deb46fb..bf65a8a 100644
--- a/fs/cachefiles/io.c
+++ b/fs/cachefiles/io.c
@@ -319,7 +319,7 @@ bool cachefiles_open_object(struct cachefiles_object *object)
 	struct file *file;
 	struct path path;
 
-	path.mnt = cache->path.mnt;
+	path.mnt = cache->cache_path.mnt;
 	path.dentry = object->dentry;
 
 	if (object->content_info == CACHEFILES_CONTENT_MAP &&
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index fd30ae8..e0a66ab 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -85,7 +85,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
 				  enum fscache_why_object_killed why)
 {
 	struct dentry *grave, *trap;
-	struct path path, path_to_graveyard;
+	struct path path;
 	char nbuffer[8 + 8 + 1];
 	int ret;
 
@@ -101,7 +101,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
 	if (!d_is_dir(rep)) {
 		_debug("unlink stale object");
 
-		path.mnt = cache->path.mnt;
+		path.mnt = cache->cache_path.mnt;
 		path.dentry = dir;
 		ret = security_path_unlink(&path, rep);
 		if (ret < 0) {
@@ -131,38 +131,38 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
 		(uint32_t) atomic_inc_return(&cache->gravecounter));
 
 	/* do the multiway lock magic */
-	trap = lock_rename(cache->graveyard, dir);
+	trap = lock_rename(cache->graveyard_path.dentry, dir);
 
 	/* do some checks before getting the grave dentry */
 	if (rep->d_parent != dir || IS_DEADDIR(d_inode(rep))) {
 		/* the entry was probably culled when we dropped the parent dir
 		 * lock */
-		unlock_rename(cache->graveyard, dir);
+		unlock_rename(cache->graveyard_path.dentry, dir);
 		_leave(" = 0 [culled?]");
 		return 0;
 	}
 
-	if (!d_can_lookup(cache->graveyard)) {
-		unlock_rename(cache->graveyard, dir);
+	if (!d_can_lookup(cache->graveyard_path.dentry)) {
+		unlock_rename(cache->graveyard_path.dentry, dir);
 		cachefiles_io_error(cache, "Graveyard no longer a directory");
 		return -EIO;
 	}
 
 	if (trap == rep) {
-		unlock_rename(cache->graveyard, dir);
+		unlock_rename(cache->graveyard_path.dentry, dir);
 		cachefiles_io_error(cache, "May not make directory loop");
 		return -EIO;
 	}
 
 	if (d_mountpoint(rep)) {
-		unlock_rename(cache->graveyard, dir);
+		unlock_rename(cache->graveyard_path.dentry, dir);
 		cachefiles_io_error(cache, "Mountpoint in cache");
 		return -EIO;
 	}
 
-	grave = lookup_one_len(nbuffer, cache->graveyard, strlen(nbuffer));
+	grave = lookup_one_len(nbuffer, cache->graveyard_path.dentry, strlen(nbuffer));
 	if (IS_ERR(grave)) {
-		unlock_rename(cache->graveyard, dir);
+		unlock_rename(cache->graveyard_path.dentry, dir);
 
 		if (PTR_ERR(grave) == -ENOMEM) {
 			_leave(" = -ENOMEM");
@@ -174,7 +174,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
 	}
 
 	if (d_is_positive(grave)) {
-		unlock_rename(cache->graveyard, dir);
+		unlock_rename(cache->graveyard_path.dentry, dir);
 		dput(grave);
 		grave = NULL;
 		cond_resched();
@@ -182,7 +182,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
 	}
 
 	if (d_mountpoint(grave)) {
-		unlock_rename(cache->graveyard, dir);
+		unlock_rename(cache->graveyard_path.dentry, dir);
 		dput(grave);
 		cachefiles_io_error(cache, "Mountpoint in graveyard");
 		return -EIO;
@@ -190,18 +190,16 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
 
 	/* target should not be an ancestor of source */
 	if (trap == grave) {
-		unlock_rename(cache->graveyard, dir);
+		unlock_rename(cache->graveyard_path.dentry, dir);
 		dput(grave);
 		cachefiles_io_error(cache, "May not make directory loop");
 		return -EIO;
 	}
 
 	/* attempt the rename */
-	path.mnt = cache->path.mnt;
+	path.mnt = cache->cache_path.mnt;
 	path.dentry = dir;
-	path_to_graveyard.mnt = cache->path.mnt;
-	path_to_graveyard.dentry = cache->graveyard;
-	ret = security_path_rename(&path, rep, &path_to_graveyard, grave, 0);
+	ret = security_path_rename(&path, rep, &cache->graveyard_path, grave, 0);
 	if (ret < 0) {
 		cachefiles_io_error(cache, "Rename security error %d", ret);
 	} else {
@@ -210,7 +208,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
 			.old_dir	= d_inode(dir),
 			.old_dentry	= rep,
 			.new_mnt_userns	= &init_user_ns,
-			.new_dir	= d_inode(cache->graveyard),
+			.new_dir	= d_inode(cache->graveyard_path.dentry),
 			.new_dentry	= grave,
 		};
 		trace_cachefiles_rename(object, rep, grave, why);
@@ -220,7 +218,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
 					    "Rename failed with error %d", ret);
 	}
 
-	unlock_rename(cache->graveyard, dir);
+	unlock_rename(cache->graveyard_path.dentry, dir);
 	dput(grave);
 	_leave(" = 0");
 	return 0;
@@ -398,7 +396,7 @@ static struct dentry *cachefiles_walk_to_volume(struct cachefiles_object *object
 	memcpy(name + 1, volume->key + 1, len);
 	name[len + 1] = 0;
 
-	dentry = cachefiles_walk_to_dir(object, &object->cache->path,
+	dentry = cachefiles_walk_to_dir(object, &object->cache->cache_path,
 					name, len + 1);
 	kfree(name);
 	if (dentry) {
@@ -449,7 +447,7 @@ static int cachefiles_check_open_object(struct cachefiles_object *object,
 		 * (this is used to keep track of culling, and atimes are only
 		 * updated by read, write and readdir but not lookup or
 		 * open) */
-		path.mnt = object->cache->path.mnt;
+		path.mnt = object->cache->cache_path.mnt;
 		path.dentry = object->dentry;
 		touch_atime(&path);
 	}
@@ -501,7 +499,7 @@ bool cachefiles_walk_to_object(struct cachefiles_object *object,
 	_enter("OBJ%x,%s,", object->debug_id, key);
 
 lookup_again:
-	path.mnt = object->cache->path.mnt;
+	path.mnt = object->cache->cache_path.mnt;
 
 	/* Walk over path "cache/vol/fanout/file". */
 	vol = cachefiles_walk_to_volume(object);
@@ -548,11 +546,11 @@ bool cachefiles_walk_to_object(struct cachefiles_object *object,
 /*
  * get a subdirectory
  */
-struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
-					struct dentry *dir,
-					const char *dirname)
+int cachefiles_get_directory(struct cachefiles_cache *cache,
+			     const char *dirname,
+			     struct path *_path)
 {
-	struct dentry *subdir;
+	struct dentry *dir = cache->root_path.dentry, *subdir;
 	unsigned long start;
 	struct path path;
 	int ret;
@@ -583,7 +581,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
 
 		_debug("attempt mkdir");
 
-		path.mnt = cache->path.mnt;
+		path.mnt = cache->cache_path.mnt;
 		path.dentry = dir;
 		ret = security_path_mkdir(&path, subdir, 0700);
 		if (ret < 0)
@@ -624,29 +622,31 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
 		goto check_error;
 
 	_leave(" = [%lu]", d_backing_inode(subdir)->i_ino);
-	return subdir;
+	_path->dentry = subdir;
+	_path->mnt = mntget(cache->root_path.mnt);
+	return 0;
 
 check_error:
 	dput(subdir);
 	_leave(" = %d [check]", ret);
-	return ERR_PTR(ret);
+	return ret;
 
 mkdir_error:
 	inode_unlock(d_inode(dir));
 	dput(subdir);
 	pr_err("mkdir %s failed with error %d\n", dirname, ret);
-	return ERR_PTR(ret);
+	return ret;
 
 lookup_error:
 	inode_unlock(d_inode(dir));
 	ret = PTR_ERR(subdir);
 	pr_err("Lookup %s failed with error %d\n", dirname, ret);
-	return ERR_PTR(ret);
+	return ret;
 
 nomem_d_alloc:
 	inode_unlock(d_inode(dir));
 	_leave(" = -ENOMEM");
-	return ERR_PTR(-ENOMEM);
+	return -ENOMEM;
 }
 
 /*