diff options
| -rw-r--r-- | fs/Kconfig | 1 | ||||
| -rw-r--r-- | fs/Makefile | 1 | ||||
| -rw-r--r-- | fs/cachefiles/Kconfig | 21 | ||||
| -rw-r--r-- | fs/cachefiles/Makefile | 18 | ||||
| -rw-r--r-- | fs/cachefiles/bind.c | 278 | ||||
| -rw-r--r-- | fs/cachefiles/daemon.c | 748 | ||||
| -rw-r--r-- | fs/cachefiles/interface.c | 572 | ||||
| -rw-r--r-- | fs/cachefiles/internal.h | 350 | ||||
| -rw-r--r-- | fs/cachefiles/io.c | 420 | ||||
| -rw-r--r-- | fs/cachefiles/key.c | 155 | ||||
| -rw-r--r-- | fs/cachefiles/main.c | 95 | ||||
| -rw-r--r-- | fs/cachefiles/namei.c | 1018 | ||||
| -rw-r--r-- | fs/cachefiles/rdwr.c | 972 | ||||
| -rw-r--r-- | fs/cachefiles/security.c | 112 | ||||
| -rw-r--r-- | fs/cachefiles/xattr.c | 324 | ||||
| -rw-r--r-- | include/trace/events/cachefiles.h | 321 |
16 files changed, 0 insertions, 5406 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index a6313a969bc5..86e311377e6e 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -132,7 +132,6 @@ menu "Caches" source "fs/netfs/Kconfig" source "fs/fscache/Kconfig" -source "fs/cachefiles/Kconfig" endmenu diff --git a/fs/Makefile b/fs/Makefile index 84c5e4cdfee5..290815f3fd31 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -125,7 +125,6 @@ obj-$(CONFIG_AFS_FS) += afs/ obj-$(CONFIG_NILFS2_FS) += nilfs2/ obj-$(CONFIG_BEFS_FS) += befs/ obj-$(CONFIG_HOSTFS) += hostfs/ -obj-$(CONFIG_CACHEFILES) += cachefiles/ obj-$(CONFIG_DEBUG_FS) += debugfs/ obj-$(CONFIG_TRACING) += tracefs/ obj-$(CONFIG_OCFS2_FS) += ocfs2/ diff --git a/fs/cachefiles/Kconfig b/fs/cachefiles/Kconfig deleted file mode 100644 index 6827b40f7ddc..000000000000 --- a/fs/cachefiles/Kconfig +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -config CACHEFILES - tristate "Filesystem caching on files" - depends on FSCACHE && BLOCK - help - This permits use of a mounted filesystem as a cache for other - filesystems - primarily networking filesystems - thus allowing fast - local disk to enhance the speed of slower devices. - - See Documentation/filesystems/caching/cachefiles.rst for more - information. - -config CACHEFILES_DEBUG - bool "Debug CacheFiles" - depends on CACHEFILES - help - This permits debugging to be dynamically enabled in the filesystem - caching on files module. If this is set, the debugging output may be - enabled by setting bits in /sys/modules/cachefiles/parameter/debug or - by including a debugging specifier in /etc/cachefilesd.conf. diff --git a/fs/cachefiles/Makefile b/fs/cachefiles/Makefile deleted file mode 100644 index 02fd17731769..000000000000 --- a/fs/cachefiles/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for caching in a mounted filesystem -# - -cachefiles-y := \ - bind.o \ - daemon.o \ - interface.o \ - io.o \ - key.o \ - main.o \ - namei.o \ - rdwr.o \ - security.o \ - xattr.o - -obj-$(CONFIG_CACHEFILES) := cachefiles.o diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c deleted file mode 100644 index d463d89f5db8..000000000000 --- a/fs/cachefiles/bind.c +++ /dev/null @@ -1,278 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* Bind and unbind a cache from the filesystem backing it - * - * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/sched.h> -#include <linux/completion.h> -#include <linux/slab.h> -#include <linux/fs.h> -#include <linux/file.h> -#include <linux/namei.h> -#include <linux/mount.h> -#include <linux/statfs.h> -#include <linux/ctype.h> -#include <linux/xattr.h> -#include "internal.h" - -static int cachefiles_daemon_add_cache(struct cachefiles_cache *caches); - -/* - * bind a directory as a cache - */ -int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args) -{ - _enter("{%u,%u,%u,%u,%u,%u},%s", - cache->frun_percent, - cache->fcull_percent, - cache->fstop_percent, - cache->brun_percent, - cache->bcull_percent, - cache->bstop_percent, - args); - - /* start by checking things over */ - ASSERT(cache->fstop_percent >= 0 && - cache->fstop_percent < cache->fcull_percent && - cache->fcull_percent < cache->frun_percent && - cache->frun_percent < 100); - - ASSERT(cache->bstop_percent >= 0 && - cache->bstop_percent < cache->bcull_percent && - cache->bcull_percent < cache->brun_percent && - cache->brun_percent < 100); - - if (*args) { - pr_err("'bind' command doesn't take an argument\n"); - return -EINVAL; - } - - if (!cache->rootdirname) { - pr_err("No cache directory specified\n"); - return -EINVAL; - } - - /* don't permit already bound caches to be re-bound */ - if (test_bit(CACHEFILES_READY, &cache->flags)) { - pr_err("Cache already bound\n"); - return -EBUSY; - } - - /* make sure we have copies of the tag and dirname strings */ - if (!cache->tag) { - /* the tag string is released by the fops->release() - * function, so we don't release it on error here */ - cache->tag = kstrdup("CacheFiles", GFP_KERNEL); - if (!cache->tag) - return -ENOMEM; - } - - /* add the cache */ - return cachefiles_daemon_add_cache(cache); -} - -/* - * add a cache - */ -static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache) -{ - struct cachefiles_object *fsdef; - struct path path; - struct kstatfs stats; - struct dentry *graveyard, *cachedir, *root; - const struct cred *saved_cred; - int ret; - - _enter(""); - - /* we want to work under the module's security ID */ - ret = cachefiles_get_security_ID(cache); - if (ret < 0) - return ret; - - cachefiles_begin_secure(cache, &saved_cred); - - /* allocate the root index object */ - ret = -ENOMEM; - - fsdef = kmem_cache_alloc(cachefiles_object_jar, GFP_KERNEL); - if (!fsdef) - goto error_root_object; - - ASSERTCMP(fsdef->backer, ==, NULL); - - atomic_set(&fsdef->usage, 1); - fsdef->type = FSCACHE_COOKIE_TYPE_INDEX; - - /* look up the directory at the root of the cache */ - ret = kern_path(cache->rootdirname, LOOKUP_DIRECTORY, &path); - if (ret < 0) - goto error_open_root; - - cache->mnt = path.mnt; - root = path.dentry; - - ret = -EINVAL; - if (mnt_user_ns(path.mnt) != &init_user_ns) { - pr_warn("File cache on idmapped mounts not supported"); - goto error_unsupported; - } - - /* check parameters */ - ret = -EOPNOTSUPP; - if (d_is_negative(root) || - !d_backing_inode(root)->i_op->lookup || - !d_backing_inode(root)->i_op->mkdir || - !(d_backing_inode(root)->i_opflags & IOP_XATTR) || - !root->d_sb->s_op->statfs || - !root->d_sb->s_op->sync_fs) - goto error_unsupported; - - ret = -EROFS; - if (sb_rdonly(root->d_sb)) - goto error_unsupported; - - /* determine the security of the on-disk cache as this governs - * security ID of files we create */ - ret = cachefiles_determine_cache_security(cache, root, &saved_cred); - if (ret < 0) - goto error_unsupported; - - /* get the cache size and blocksize */ - ret = vfs_statfs(&path, &stats); - if (ret < 0) - goto error_unsupported; - - ret = -ERANGE; - if (stats.f_bsize <= 0) - goto error_unsupported; - - ret = -EOPNOTSUPP; - if (stats.f_bsize > PAGE_SIZE) - goto error_unsupported; - - cache->bsize = stats.f_bsize; - cache->bshift = 0; - if (stats.f_bsize < PAGE_SIZE) - cache->bshift = PAGE_SHIFT - ilog2(stats.f_bsize); - - _debug("blksize %u (shift %u)", - cache->bsize, cache->bshift); - - _debug("size %llu, avail %llu", - (unsigned long long) stats.f_blocks, - (unsigned long long) stats.f_bavail); - - /* set up caching limits */ - do_div(stats.f_files, 100); - cache->fstop = stats.f_files * cache->fstop_percent; - cache->fcull = stats.f_files * cache->fcull_percent; - cache->frun = stats.f_files * cache->frun_percent; - - _debug("limits {%llu,%llu,%llu} files", - (unsigned long long) cache->frun, - (unsigned long long) cache->fcull, - (unsigned long long) cache->fstop); - - stats.f_blocks >>= cache->bshift; - do_div(stats.f_blocks, 100); - cache->bstop = stats.f_blocks * cache->bstop_percent; - cache->bcull = stats.f_blocks * cache->bcull_percent; - cache->brun = stats.f_blocks * cache->brun_percent; - - _debug("limits {%llu,%llu,%llu} blocks", - (unsigned long long) cache->brun, - (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); - goto error_unsupported; - } - - fsdef->dentry = cachedir; - fsdef->fscache.cookie = NULL; - - ret = cachefiles_check_object_type(fsdef); - if (ret < 0) - goto error_unsupported; - - /* get the graveyard directory */ - graveyard = cachefiles_get_directory(cache, root, "graveyard"); - if (IS_ERR(graveyard)) { - ret = PTR_ERR(graveyard); - goto error_unsupported; - } - - cache->graveyard = graveyard; - - /* publish the cache */ - fscache_init_cache(&cache->cache, - &cachefiles_cache_ops, - "%s", - fsdef->dentry->d_sb->s_id); - - fscache_object_init(&fsdef->fscache, &fscache_fsdef_index, - &cache->cache); - - ret = fscache_add_cache(&cache->cache, &fsdef->fscache, cache->tag); - if (ret < 0) - goto error_add_cache; - - /* done */ - set_bit(CACHEFILES_READY, &cache->flags); - dput(root); - - pr_info("File cache on %s registered\n", cache->cache.identifier); - - /* check how much space the cache has */ - cachefiles_has_space(cache, 0, 0); - cachefiles_end_secure(cache, saved_cred); - return 0; - -error_add_cache: - dput(cache->graveyard); - cache->graveyard = NULL; -error_unsupported: - mntput(cache->mnt); - cache->mnt = NULL; - dput(fsdef->dentry); - fsdef->dentry = NULL; - dput(root); -error_open_root: - kmem_cache_free(cachefiles_object_jar, fsdef); -error_root_object: - cachefiles_end_secure(cache, saved_cred); - pr_err("Failed to register: %d\n", ret); - return ret; -} - -/* - * unbind a cache on fd release - */ -void cachefiles_daemon_unbind(struct cachefiles_cache *cache) -{ - _enter(""); - - if (test_bit(CACHEFILES_READY, &cache->flags)) { - pr_info("File cache on %s unregistering\n", - cache->cache.identifier); - - fscache_withdraw_cache(&cache->cache); - } - - dput(cache->graveyard); - mntput(cache->mnt); - - kfree(cache->rootdirname); - kfree(cache->secctx); - kfree(cache->tag); - - _leave(""); -} diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c deleted file mode 100644 index 752c1e43416f..000000000000 --- a/fs/cachefiles/daemon.c +++ /dev/null @@ -1,748 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* Daemon interface - * - * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/sched.h> -#include <linux/completion.h> -#include <linux/slab.h> -#include <linux/fs.h> -#include <linux/file.h> -#include <linux/namei.h> -#include <linux/poll.h> -#include <linux/mount.h> -#include <linux/statfs.h> -#include <linux/ctype.h> -#include <linux/string.h> -#include <linux/fs_struct.h> -#include "internal.h" - -static int cachefiles_daemon_open(struct inode *, struct file *); -static int cachefiles_daemon_release(struct inode *, struct file *); -static ssize_t cachefiles_daemon_read(struct file *, char __user *, size_t, - loff_t *); -static ssize_t cachefiles_daemon_write(struct file *, const char __user *, - size_t, loff_t *); -static __poll_t cachefiles_daemon_poll(struct file *, - struct poll_table_struct *); -static int cachefiles_daemon_frun(struct cachefiles_cache *, char *); -static int cachefiles_daemon_fcull(struct cachefiles_cache *, char *); -static int cachefiles_daemon_fstop(struct cachefiles_cache *, char *); -static int cachefiles_daemon_brun(struct cachefiles_cache *, char *); -static int cachefiles_daemon_bcull(struct cachefiles_cache *, char *); -static int cachefiles_daemon_bstop(struct cachefiles_cache *, char *); -static int cachefiles_daemon_cull(struct cachefiles_cache *, char *); -static int cachefiles_daemon_debug(struct cachefiles_cache *, char *); -static int cachefiles_daemon_dir(struct cachefiles_cache *, char *); -static int cachefiles_daemon_inuse(struct cachefiles_cache *, char *); -static int cachefiles_daemon_secctx(struct cachefiles_cache *, char *); -static int cachefiles_daemon_tag(struct cachefiles_cache *, char *); - -static unsigned long cachefiles_open; - -const struct file_operations cachefiles_daemon_fops = { - .owner = THIS_MODULE, - .open = cachefiles_daemon_open, - .release = cachefiles_daemon_release, - .read = cachefiles_daemon_read, - .write = cachefiles_daemon_write, - .poll = cachefiles_daemon_poll, - .llseek = noop_llseek, -}; - -struct cachefiles_daemon_cmd { - char name[8]; - int (*handler)(struct cachefiles_cache *cache, char *args); -}; - -static const struct cachefiles_daemon_cmd cachefiles_daemon_cmds[] = { - { "bind", cachefiles_daemon_bind }, - { "brun", cachefiles_daemon_brun }, - { "bcull", cachefiles_daemon_bcull }, - { "bstop", cachefiles_daemon_bstop }, - { "cull", cachefiles_daemon_cull }, - { "debug", cachefiles_daemon_debug }, - { "dir", cachefiles_daemon_dir }, - { "frun", cachefiles_daemon_frun }, - { "fcull", cachefiles_daemon_fcull }, - { "fstop", cachefiles_daemon_fstop }, - { "inuse", cachefiles_daemon_inuse }, - { "secctx", cachefiles_daemon_secctx }, - { "tag", cachefiles_daemon_tag }, - { "", NULL } -}; - - -/* - * do various checks - */ -static int cachefiles_daemon_open(struct inode *inode, struct file *file) -{ - struct cachefiles_cache *cache; - - _enter(""); - - /* only the superuser may do this */ - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - /* the cachefiles device may only be open once at a time */ - if (xchg(&cachefiles_open, 1) == 1) - return -EBUSY; - - /* allocate a cache record */ - cache = kzalloc(sizeof(struct cachefiles_cache), GFP_KERNEL); - if (!cache) { - cachefiles_open = 0; - return -ENOMEM; - } - - mutex_init(&cache->daemon_mutex); - cache->active_nodes = RB_ROOT; - rwlock_init(&cache->active_lock); - init_waitqueue_head(&cache->daemon_pollwq); - - /* set default caching limits - * - limit at 1% free space and/or free files - * - cull below 5% free space and/or free files - * - cease culling above 7% free space and/or free files - */ - cache->frun_percent = 7; - cache->fcull_percent = 5; - cache->fstop_percent = 1; - cache->brun_percent = 7; - cache->bcull_percent = 5; - cache->bstop_percent = 1; - - file->private_data = cache; - cache->cachefilesd = file; - return 0; -} - -/* - * release a cache - */ -static int cachefiles_daemon_release(struct inode *inode, struct file *file) -{ - struct cachefiles_cache *cache = file->private_data; - - _enter(""); - - ASSERT(cache); - - set_bit(CACHEFILES_DEAD, &cache->flags); - - cachefiles_daemon_unbind(cache); - - ASSERT(!cache->active_nodes.rb_node); - - /* clean up the control file interface */ - cache->cachefilesd = NULL; - file->private_data = NULL; - cachefiles_open = 0; - - kfree(cache); - - _leave(""); - return 0; -} - -/* - * read the cache state - */ -static ssize_t cachefiles_daemon_read(struct file *file, char __user *_buffer, - size_t buflen, loff_t *pos) -{ - struct cachefiles_cache *cache = file->private_data; - unsigned long long b_released; - unsigned f_released; - char buffer[256]; - int n; - - //_enter(",,%zu,", buflen); - - if (!test_bit(CACHEFILES_READY, &cache->flags)) - return 0; - - /* check how much space the cache has */ - cachefiles_has_space(cache, 0, 0); - - /* summarise */ - f_released = atomic_xchg(&cache->f_released, 0); - b_released = atomic_long_xchg(&cache->b_released, 0); - clear_bit(CACHEFILES_STATE_CHANGED, &cache->flags); - - n = snprintf(buffer, sizeof(buffer), - "cull=%c" - " frun=%llx" - " fcull=%llx" - " fstop=%llx" - " brun=%llx" - " bcull=%llx" - " bstop=%llx" - " freleased=%x" - " breleased=%llx", - test_bit(CACHEFILES_CULLING, &cache->flags) ? '1' : '0', - (unsigned long long) cache->frun, - (unsigned long long) cache->fcull, - (unsigned long long) cache->fstop, - (unsigned long long) cache->brun, - (unsigned long long) cache->bcull, - (unsigned long long) cache->bstop, - f_released, - b_released); - - if (n > buflen) - return -EMSGSIZE; - - if (copy_to_user(_buffer, buffer, n) != 0) - return -EFAULT; - - return n; -} - -/* - * command the cache - */ -static ssize_t cachefiles_daemon_write(struct file *file, - const char __user *_data, - size_t datalen, - loff_t *pos) -{ - const struct cachefiles_daemon_cmd *cmd; - struct cachefiles_cache *cache = file->private_data; - ssize_t ret; - char *data, *args, *cp; - - //_enter(",,%zu,", datalen); - - ASSERT(cache); - - if (test_bit(CACHEFILES_DEAD, &cache->flags)) - return -EIO; - - if (datalen < 0 || datalen > PAGE_SIZE - 1) - return -EOPNOTSUPP; - - /* drag the command string into the kernel so we can parse it */ - data = memdup_user_nul(_data, datalen); - if (IS_ERR(data)) - return PTR_ERR(data); - - ret = -EINVAL; - if (memchr(data, '\0', datalen)) - goto error; - - /* strip any newline */ - cp = memchr(data, '\n', datalen); - if (cp) { - if (cp == data) - goto error; - - *cp = '\0'; - } - - /* parse the command */ - ret = -EOPNOTSUPP; - - for (args = data; *args; args++) - if (isspace(*args)) - break; - if (*args) { - if (args == data) - goto error; - *args = '\0'; - args = skip_spaces(++args); - } - - /* run the appropriate command handler */ - for (cmd = cachefiles_daemon_cmds; cmd->name[0]; cmd++) - if (strcmp(cmd->name, data) == 0) - goto found_command; - -error: - kfree(data); - //_leave(" = %zd", ret); - return ret; - -found_command: - mutex_lock(&cache->daemon_mutex); - - ret = -EIO; - if (!test_bit(CACHEFILES_DEAD, &cache->flags)) - ret = cmd->handler(cache, args); - - mutex_unlock(&cache->daemon_mutex); - - if (ret == 0) - ret = datalen; - goto error; -} - -/* - * poll for culling state - * - use EPOLLOUT to indicate culling state - */ -static __poll_t cachefiles_daemon_poll(struct file *file, - struct poll_table_struct *poll) -{ - struct cachefiles_cache *cache = file->private_data; - __poll_t mask; - - poll_wait(file, &cache->daemon_pollwq, poll); - mask = 0; - - if (test_bit(CACHEFILES_STATE_CHANGED, &cache->flags)) - mask |= EPOLLIN; - - if (test_bit(CACHEFILES_CULLING, &cache->flags)) - mask |= EPOLLOUT; - - return mask; -} - -/* - * give a range error for cache space constraints - * - can be tail-called - */ -static int cachefiles_daemon_range_error(struct cachefiles_cache *cache, - char *args) -{ - pr_err("Free space limits must be in range 0%%<=stop<cull<run<100%%\n"); - - return -EINVAL; -} - -/* - * set the percentage of files at which to stop culling - * - command: "frun <N>%" - */ -static int cachefiles_daemon_frun(struct cachefiles_cache *cache, char *args) -{ - unsigned long frun; - - _enter(",%s", args); - - if (!*args) - return -EINVAL; - - frun = simple_strtoul(args, &args, 10); - if (args[0] != '%' || args[1] != '\0') - return -EINVAL; - - if (frun <= cache->fcull_percent || frun >= 100) - return cachefiles_daemon_range_error(cache, args); - - cache->frun_percent = frun; - return 0; -} - -/* - * set the percentage of files at which to start culling - * - command: "fcull <N>%" - */ -static int cachefiles_daemon_fcull(struct cachefiles_cache *cache, char *args) -{ - unsigned long fcull; - - _enter(",%s", args); - - if (!*args) - return -EINVAL; - - fcull = simple_strtoul(args, &args, 10); - if (args[0] != '%' || args[1] != '\0') - return -EINVAL; - - if (fcull <= cache->fstop_percent || fcull >= cache->frun_percent) - return cachefiles_daemon_range_error(cache, args); - - cache->fcull_percent = fcull; - return 0; -} - -/* - * set the percentage of files at which to stop allocating - * - command: "fstop <N>%" - */ -static int cachefiles_daemon_fstop(struct cachefiles_cache *cache, char *args) -{ - unsigned long fstop; - - _enter(",%s", args); - - if (!*args) - return -EINVAL; - - fstop = simple_strtoul(args, &args, 10); - if (args[0] != '%' || args[1] != '\0') - return -EINVAL; - - if (fstop < 0 || fstop >= cache->fcull_percent) - return cachefiles_daemon_range_error(cache, args); - - cache->fstop_percent = fstop; - return 0; -} - -/* - * set the percentage of blocks at which to stop culling - * - command: "brun <N>%" - */ -static int cachefiles_daemon_brun(struct cachefiles_cache *cache, char *args) -{ - unsigned long brun; - - _enter(",%s", args); - - if (!*args) - return -EINVAL; - - brun = simple_strtoul(args, &args, 10); - if (args[0] != '%' || args[1] != '\0') - return -EINVAL; - - if (brun <= cache->bcull_percent || brun >= 100) - return cachefiles_daemon_range_error(cache, args); - - cache->brun_percent = brun; - return 0; -} - -/* - * set the percentage of blocks at which to start culling - * - command: "bcull <N>%" - */ -static int cachefiles_daemon_bcull(struct cachefiles_cache *cache, char *args) -{ - unsigned long bcull; - - _enter(",%s", args); - - if (!*args) - return -EINVAL; - - bcull = simple_strtoul(args, &args, 10); - if (args[0] != '%' || args[1] != '\0') - return -EINVAL; - - if (bcull <= cache->bstop_percent || bcull >= cache->brun_percent) - return cachefiles_daemon_range_error(cache, args); - - cache->bcull_percent = bcull; - return 0; -} - -/* - * set the percentage of blocks at which to stop allocating - * - command: "bstop <N>%" - */ -static int cachefiles_daemon_bstop(struct cachefiles_cache *cache, char *args) -{ - unsigned long bstop; - - _enter(",%s", args); - - if (!*args) - return -EINVAL; - - bstop = simple_strtoul(args, &args, 10); - if (args[0] != '%' || args[1] != '\0') - return -EINVAL; - - if (bstop < 0 || bstop >= cache->bcull_percent) - return cachefiles_daemon_range_error(cache, args); - - cache->bstop_percent = bstop; - return 0; -} - -/* - * set the cache directory - * - command: "dir <name>" - */ -static int cachefiles_daemon_dir(struct cachefiles_cache *cache, char *args) -{ - char *dir; - - _enter(",%s", args); - - if (!*args) { - pr_err("Empty directory specified\n"); - return -EINVAL; - } - - if (cache->rootdirname) { - pr_err("Second cache directory specified\n"); - return -EEXIST; - } - - dir = kstrdup(args, GFP_KERNEL); - if (!dir) - return -ENOMEM; - - cache->rootdirname = dir; - return 0; -} - -/* - * set the cache security context - * - command: "secctx <ctx>" - */ -static int cachefiles_daemon_secctx(struct cachefiles_cache *cache, char *args) -{ - char *secctx; - - _enter(",%s", args); - - if (!*args) { - pr_err("Empty security context specified\n"); - return -EINVAL; - } - - if (cache->secctx) { - pr_err("Second security context specified\n"); - return -EINVAL; - } - - secctx = kstrdup(args, GFP_KERNEL); - if (!secctx) - return -ENOMEM; - - cache->secctx = secctx; - return 0; -} - -/* - * set the cache tag - * - command: "tag <name>" - */ -static int cachefiles_daemon_tag(struct cachefiles_cache *cache, char *args) -{ - char *tag; - - _enter(",%s", args); - - if (!*args) { - pr_err("Empty tag specified\n"); - return -EINVAL; - } - - if (cache->tag) - return -EEXIST; - - tag = kstrdup(args, GFP_KERNEL); - if (!tag) - return -ENOMEM; - - cache->tag = tag; - return 0; -} - -/* - * request a node in the cache be culled from the current working directory - * - command: "cull <name>" - */ -static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args) -{ - struct path path; - const struct cred *saved_cred; - int ret; - - _enter(",%s", args); - - if (strchr(args, '/')) - goto inval; - - if (!test_bit(CACHEFILES_READY, &cache->flags)) { - pr_err("cull applied to unready cache\n"); - return -EIO; - } - - if (test_bit(CACHEFILES_DEAD, &cache->flags)) { - pr_err("cull applied to dead cache\n"); - return -EIO; - } - - /* extract the directory dentry from the cwd */ - get_fs_pwd(current->fs, &path); - - if (!d_can_lookup(path.dentry)) - goto notdir; - - cachefiles_begin_secure(cache, &saved_cred); - ret = cachefiles_cull(cache, path.dentry, args); - cachefiles_end_secure(cache, saved_cred); - - path_put(&path); - _leave(" = %d", ret); - return ret; - -notdir: - path_put(&path); - pr_err("cull command requires dirfd to be a directory\n"); - return -ENOTDIR; - -inval: - pr_err("cull command requires dirfd and filename\n"); - return -EINVAL; -} - -/* - * set debugging mode - * - command: "debug <mask>" - */ -static int cachefiles_daemon_debug(struct cachefiles_cache *cache, char *args) -{ - unsigned long mask; - - _enter(",%s", args); - - mask = simple_strtoul(args, &args, 0); - if (args[0] != '\0') - goto inval; - - cachefiles_debug = mask; - _leave(" = 0"); - return 0; - -inval: - pr_err("debug command requires mask\n"); - return -EINVAL; -} - -/* - * find out whether an object in the current working directory is in use or not - * - command: "inuse <name>" - */ -static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args) -{ - struct path path; - const struct cred *saved_cred; - int ret; - - //_enter(",%s", args); - - if (strchr(args, '/')) - goto inval; - - if (!test_bit(CACHEFILES_READY, &cache->flags)) { - pr_err("inuse applied to unready cache\n"); - return -EIO; - } - - if (test_bit(CACHEFILES_DEAD, &cache->flags)) { - pr_err("inuse applied to dead cache\n"); - return -EIO; - } - - /* extract the directory dentry from the cwd */ - get_fs_pwd(current->fs, &path); - - if (!d_can_lookup(path.dentry)) - goto notdir; - - cachefiles_begin_secure(cache, &saved_cred); - ret = cachefiles_check_in_use(cache, path.dentry, args); - cachefiles_end_secure(cache, saved_cred); - - path_put(&path); - //_leave(" = %d", ret); - return ret; - -notdir: - path_put(&path); - pr_err("inuse command requires dirfd to be a directory\n"); - return -ENOTDIR; - -inval: - pr_err("inuse command requires dirfd and filename\n"); - return -EINVAL; -} - -/* - * see if we have space for a number of pages and/or a number of files in the - * cache - */ -int cachefiles_has_space(struct cachefiles_cache *cache, - unsigned fnr, unsigned bnr) -{ - struct kstatfs stats; - struct path path = { - .mnt = cache->mnt, - .dentry = cache->mnt->mnt_root, - }; - int ret; - - //_enter("{%llu,%llu,%llu,%llu,%llu,%llu},%u,%u", - // (unsigned long long) cache->frun, - // (unsigned long long) cache->fcull, - // (unsigned long long) cache->fstop, - // (unsigned long long) cache->brun, - // (unsigned long long) cache->bcull, - // (unsigned long long) cache->bstop, - // fnr, bnr); - - /* find out how many pages of blockdev are available */ - memset(&stats, 0, sizeof(stats)); - - ret = vfs_statfs(&path, &stats); - if (ret < 0) { - if (ret == -EIO) - cachefiles_io_error(cache, "statfs failed"); - _leave(" = %d", ret); - return ret; - } - - stats.f_bavail >>= cache->bshift; - - //_debug("avail %llu,%llu", - // (unsigned long long) stats.f_ffree, - // (unsigned long long) stats.f_bavail); - - /* see if there is sufficient space */ - if (stats.f_ffree > fnr) - stats.f_ffree -= fnr; - else - stats.f_ffree = 0; - - if (stats.f_bavail > bnr) - stats.f_bavail -= bnr; - else - stats.f_bavail = 0; - - ret = -ENOBUFS; - if (stats.f_ffree < cache->fstop || - stats.f_bavail < cache->bstop) - goto begin_cull; - - ret = 0; - if (stats.f_ffree < cache->fcull || - stats.f_bavail < cache->bcull) - goto begin_cull; - - if (test_bit(CACHEFILES_CULLING, &cache->flags) && - stats.f_ffree >= cache->frun && - stats.f_bavail >= cache->brun && - test_and_clear_bit(CACHEFILES_CULLING, &cache->flags) - ) { - _debug("cease culling"); - cachefiles_state_changed(cache); - } - - //_leave(" = 0"); - return 0; - -begin_cull: - if (!test_and_set_bit(CACHEFILES_CULLING, &cache->flags)) { - _debug("### CULL CACHE ###"); - cachefiles_state_changed(cache); - } - - _leave(" = %d", ret); - return ret; -} diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c deleted file mode 100644 index da28ac1fa225..000000000000 --- a/fs/cachefiles/interface.c + |
