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