summaryrefslogtreecommitdiff
path: root/ANDROID_3.4.5/fs/cachefiles
diff options
context:
space:
mode:
authorSrikant Patnaik2015-01-11 12:28:04 +0530
committerSrikant Patnaik2015-01-11 12:28:04 +0530
commit871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch)
tree8718f573808810c2a1e8cb8fb6ac469093ca2784 /ANDROID_3.4.5/fs/cachefiles
parent9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff)
downloadFOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz
FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2
FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized. Changes are basically to make it look like kernel structure.
Diffstat (limited to 'ANDROID_3.4.5/fs/cachefiles')
-rw-r--r--ANDROID_3.4.5/fs/cachefiles/Kconfig39
-rw-r--r--ANDROID_3.4.5/fs/cachefiles/Makefile18
-rw-r--r--ANDROID_3.4.5/fs/cachefiles/bind.c281
-rw-r--r--ANDROID_3.4.5/fs/cachefiles/daemon.c752
-rw-r--r--ANDROID_3.4.5/fs/cachefiles/interface.c469
-rw-r--r--ANDROID_3.4.5/fs/cachefiles/internal.h354
-rw-r--r--ANDROID_3.4.5/fs/cachefiles/key.c159
-rw-r--r--ANDROID_3.4.5/fs/cachefiles/main.c106
-rw-r--r--ANDROID_3.4.5/fs/cachefiles/namei.c989
-rw-r--r--ANDROID_3.4.5/fs/cachefiles/proc.c134
-rw-r--r--ANDROID_3.4.5/fs/cachefiles/rdwr.c984
-rw-r--r--ANDROID_3.4.5/fs/cachefiles/security.c120
-rw-r--r--ANDROID_3.4.5/fs/cachefiles/xattr.c292
13 files changed, 0 insertions, 4697 deletions
diff --git a/ANDROID_3.4.5/fs/cachefiles/Kconfig b/ANDROID_3.4.5/fs/cachefiles/Kconfig
deleted file mode 100644
index 80e9c616..00000000
--- a/ANDROID_3.4.5/fs/cachefiles/Kconfig
+++ /dev/null
@@ -1,39 +0,0 @@
-
-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.txt 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.
-
-config CACHEFILES_HISTOGRAM
- bool "Gather latency information on CacheFiles"
- depends on CACHEFILES && PROC_FS
- help
-
- This option causes latency information to be gathered on CacheFiles
- operation and exported through file:
-
- /proc/fs/cachefiles/histogram
-
- The generation of this histogram adds a certain amount of overhead to
- execution as there are a number of points at which data is gathered,
- and on a multi-CPU system these may be on cachelines that keep
- bouncing between CPUs. On the other hand, the histogram may be
- useful for debugging purposes. Saying 'N' here is recommended.
-
- See Documentation/filesystems/caching/cachefiles.txt for more
- information.
diff --git a/ANDROID_3.4.5/fs/cachefiles/Makefile b/ANDROID_3.4.5/fs/cachefiles/Makefile
deleted file mode 100644
index 32cbab0f..00000000
--- a/ANDROID_3.4.5/fs/cachefiles/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Makefile for caching in a mounted filesystem
-#
-
-cachefiles-y := \
- bind.o \
- daemon.o \
- interface.o \
- key.o \
- main.o \
- namei.o \
- rdwr.o \
- security.o \
- xattr.o
-
-cachefiles-$(CONFIG_CACHEFILES_HISTOGRAM) += proc.o
-
-obj-$(CONFIG_CACHEFILES) := cachefiles.o
diff --git a/ANDROID_3.4.5/fs/cachefiles/bind.c b/ANDROID_3.4.5/fs/cachefiles/bind.c
deleted file mode 100644
index 622f4696..00000000
--- a/ANDROID_3.4.5/fs/cachefiles/bind.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/* 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)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#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 "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) {
- kerror("'bind' command doesn't take an argument");
- return -EINVAL;
- }
-
- if (!cache->rootdirname) {
- kerror("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");
- 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;
-
- _debug("- fsdef %p", fsdef);
-
- /* 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;
-
- /* 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->s_op->statfs ||
- !root->d_sb->s_op->sync_fs)
- goto error_unsupported;
-
- ret = -EROFS;
- if (root->d_sb->s_flags & MS_RDONLY)
- 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, NULL, &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);
-
- printk(KERN_INFO "CacheFiles:"
- " 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);
- kerror("Failed to register: %d", 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)) {
- printk(KERN_INFO "CacheFiles:"
- " 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/ANDROID_3.4.5/fs/cachefiles/daemon.c b/ANDROID_3.4.5/fs/cachefiles/daemon.c
deleted file mode 100644
index 0a1467b1..00000000
--- a/ANDROID_3.4.5/fs/cachefiles/daemon.c
+++ /dev/null
@@ -1,752 +0,0 @@
-/* Daemon interface
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#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 unsigned int 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;
- 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 */
- 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",
- 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
- );
-
- 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 = kmalloc(datalen + 1, GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- ret = -EFAULT;
- if (copy_from_user(data, _data, datalen) != 0)
- goto error;
-
- data[datalen] = '\0';
-
- 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 POLLOUT to indicate culling state
- */
-static unsigned int cachefiles_daemon_poll(struct file *file,
- struct poll_table_struct *poll)
-{
- struct cachefiles_cache *cache = file->private_data;
- unsigned int mask;
-
- poll_wait(file, &cache->daemon_pollwq, poll);
- mask = 0;
-
- if (test_bit(CACHEFILES_STATE_CHANGED, &cache->flags))
- mask |= POLLIN;
-
- if (test_bit(CACHEFILES_CULLING, &cache->flags))
- mask |= POLLOUT;
-
- 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)
-{
- kerror("Free space limits must be in range"
- " 0%%<=stop<cull<run<100%%");
-
- 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) {
- kerror("Empty directory specified");
- return -EINVAL;
- }
-
- if (cache->rootdirname) {
- kerror("Second cache directory specified");
- 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) {
- kerror("Empty security context specified");
- return -EINVAL;
- }
-
- if (cache->secctx) {
- kerror("Second security context specified");
- 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) {
- kerror("Empty tag specified");
- 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)) {
- kerror("cull applied to unready cache");
- return -EIO;
- }
-
- if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
- kerror("cull applied to dead cache");
- return -EIO;
- }
-
- /* extract the directory dentry from the cwd */
- get_fs_pwd(current->fs, &path);
-
- if (!S_ISDIR(path.dentry->d_inode->i_mode))
- 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);
- kerror("cull command requires dirfd to be a directory");
- return -ENOTDIR;
-
-inval:
- kerror("cull command requires dirfd and filename");
- 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:
- kerror("debug command requires mask");
- 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)) {
- kerror("inuse applied to unready cache");
- return -EIO;
- }
-
- if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
- kerror("inuse applied to dead cache");
- return -EIO;
- }
-
- /* extract the directory dentry from the cwd */
- get_fs_pwd(current->fs, &path);
-
- if (!S_ISDIR(path.dentry->d_inode->i_mode))
- 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);
- kerror("inuse command requires dirfd to be a directory");
- return -ENOTDIR;
-
-inval:
- kerror("inuse command requires dirfd and filename");
- 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/ANDROID_3.4.5/fs/cachefiles/interface.c b/ANDROID_3.4.5/fs/cachefiles/interface.c
deleted file mode 100644
index 67bef6d0..00000000
--- a/ANDROID_3.4.5/fs/cachefiles/interface.c
+++ /dev/null
@@ -1,469 +0,0 @@
-/* FS-Cache interface to CacheFiles
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#include <linux/slab.h>
-#include <linux/mount.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 */
-};
-
-static int cachefiles_attr_changed(struct fscache_object *_object);
-
-/*
- * allocate an object record for a cookie lookup and prepare the lookup data
- */
-static struct fscache_object *cachefiles_alloc_object(
- struct fscache_cache *_cache,
- struct fscache_cookie *cookie)
-{
- struct cachefiles_lookup_data *lookup_data;
- struct cachefiles_object *object;
- struct cachefiles_cache *cache;
- struct cachefiles_xattr *auxdata;
- unsigned keylen, auxlen;
- void *buffer;
- char *key;
-
- cache = container_of(_cache, struct cachefiles_cache, cache);
-
- _enter("{%s},%p,", cache->cache.identifier, cookie);
-
- lookup_data = kmalloc(sizeof(*lookup_data), GFP_KERNEL);
- 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);
- if (!object)
- goto nomem_object;
-
- ASSERTCMP(object->backer, ==, NULL);
-
- BUG_ON(test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags));
- atomic_set(&object->usage, 1);
-
- fscache_object_init(&object->fscache, cookie, &cache->cache);
-
- object->type = cookie->def->type;
-
- /* get hold of the raw key
- * - stick the length on the front and leave space on the back for the
- * encoder
- */
- buffer = kmalloc((2 + 512) + 3, GFP_KERNEL);
- if (!buffer)
- goto nomem_buffer;
-
- keylen = cookie->def->get_key(cookie->netfs_data, buffer + 2, 512);
- ASSERTCMP(keylen, <, 512);
-
- *(uint16_t *)buffer = keylen;
- ((char *)buffer)[keylen + 2] = 0;
- ((char *)buffer)[keylen + 3] = 0;
- ((char *)buffer)[keylen + 4] = 0;
-
- /* turn the raw key into something that can work with as a filename */
- key = cachefiles_cook_key(buffer, keylen + 2, object->type);
- if (!key)
- goto nomem_key;
-
- /* get hold of the auxiliary data and prepend the object type */
- auxdata = buffer;
- auxlen = 0;
- if (cookie->def->get_aux) {
- auxlen = cookie->def->get_aux(cookie->netfs_data,
- auxdata->data, 511);
- ASSERTCMP(auxlen, <, 511);
- }
-
- auxdata->len = auxlen + 1;
- auxdata->type = cookie->def->type;
-
- lookup_data->auxdata = auxdata;
- lookup_data->key = key;
- object->lookup_data = lookup_data;
-
- _leave(" = %p [%p]", &object->fscache, lookup_data);
- return &object->fscache;
-
-nomem_key:
- kfree(buffer);
-nomem_buffer:
- BUG_ON(test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags));
- kmem_cache_free(cachefiles_object_jar, object);
- fscache_object_destroyed(&cache->cache);
-nomem_object:
- kfree(lookup_data);
-nomem_lookup_data:
- _leave(" = -ENOMEM");
- return ERR_PTR(-ENOMEM);
-}
-
-/*
- * attempt to look up the nominated node in this cache
- * - return -ETIMEDOUT to be scheduled again
- */
-static int cachefiles_lookup_object(struct fscache_object *_object)
-{
- struct cachefiles_lookup_data *lookup_data;
- struct cachefiles_object *parent, *object;
- struct cachefiles_cache *cache;
- const struct cred *saved_cred;
- int ret;
-
- _enter("{OBJ%x}", _object->debug_id);
-
- cache = container_of(_object->cache, struct cachefiles_cache, cache);
- parent = container_of(_object->parent,
- struct cachefiles_object, fscache);
- object = container_of(_object, struct cachefiles_object, fscache);
- lookup_data = object->lookup_data;
-
- ASSERTCMP(lookup_data, !=, NULL);
-
- /* look up the key, creating any missing bits */
- cachefiles_begin_secure(cache, &saved_cred);
- ret = cachefiles_walk_to_object(parent, object,
- lookup_data->key,
- lookup_data->auxdata);
- cachefiles_end_secure(cache, saved_cred);
-
- /* polish off by setting the attributes of non-index files */
- if (ret == 0 &&
- object->fscache.cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX)
- cachefiles_attr_changed(&object->fscache);
-
- if (ret < 0 && ret != -ETIMEDOUT) {
- if (ret != -ENOBUFS)
- printk(KERN_WARNING
- "CacheFiles: Lookup failed error %d\n", ret);
- fscache_object_lookup_error(&object->fscache);
- }
-
- _leave(" [%d]", ret);
- return ret;
-}
-
-/*
- * indication of lookup completion
- */
-static void cachefiles_lookup_complete(struct fscache_object *_object)
-{
- struct cachefiles_object *object;
-
- object = container_of(_object, struct cachefiles_object, fscache);
-
- _enter("{OBJ%x,%p}", object->fscache.debug_id, object->lookup_data);
-
- if (object->lookup_data) {
- kfree(object->lookup_data->key);
- kfree(object->lookup_data->auxdata);
- kfree(object->lookup_data);
- object->lookup_data = NULL;
- }
-}
-
-/*
- * increment the usage count on an inode object (may fail if unmounting)
- */
-static
-struct fscache_object *cachefiles_grab_object(struct fscache_object *_object)
-{
- struct cachefiles_object *object =
- container_of(_object, struct cachefiles_object, fscache);
-
- _enter("{OBJ%x,%d}", _object->debug_id, atomic_read(&object->usage));
-
-#ifdef CACHEFILES_DEBUG_SLAB
- ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
-#endif
-
- atomic_inc(&object->usage);
- return &object->fscache;
-}
-
-/*
- * update the auxiliary data for an object object on disk
- */
-static void cachefiles_update_object(struct fscache_object *_object)
-{
- struct cachefiles_object *object;
- struct cachefiles_xattr *auxdata;
- struct cachefiles_cache *cache;
- struct fscache_cookie *cookie;
- const struct cred *saved_cred;
- unsigned auxlen;
-
- _enter("{OBJ%x}", _object->debug_id);
-
- object = container_of(_object, struct cachefiles_object, fscache);
- cache = container_of(object->fscache.cache, struct cachefiles_cache,
- cache);
- cookie = object->fscache.cookie;
-
- if (!cookie->def->get_aux) {
- _leave(" [no aux]");
- return;
- }
-
- auxdata = kmalloc(2 + 512 + 3, GFP_KERNEL);
- if (!auxdata) {
- _leave(" [nomem]");
- return;
- }
-
- auxlen = cookie->def->get_aux(cookie->netfs_data, auxdata->data, 511);
- ASSERTCMP(auxlen, <, 511);
-
- auxdata->len = auxlen + 1;
- auxdata->type = cookie->def->type;
-
- cachefiles_begin_secure(cache, &saved_cred);
- cachefiles_update_object_xattr(object, auxdata);
- cachefiles_end_secure(cache, saved_cred);
- kfree(auxdata);
- _leave("");
-}
-
-/*
- * discard the resources pinned by an object and effect retirement if
- * requested
- */
-static void cachefiles_drop_object(struct fscache_object *_object)
-{
- struct cachefiles_object *object;
- struct cachefiles_cache *cache;
- const struct cred *saved_cred;
-
- ASSERT(_object);
-
- object = container_of(_object, struct cachefiles_object, fscache);
-
- _enter("{OBJ%x,%d}",
- object->fscache.debug_id, atomic_read(&object->usage));
-
- cache = container_of(object->fscache.cache,
- struct cachefiles_cache, cache);
-
-#ifdef CACHEFILES_DEBUG_SLAB
- ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
-#endif
-
- /* delete retired objects */
- if (object->fscache.state == FSCACHE_OBJECT_RECYCLING &&
- _object != cache->cache.fsdef
- ) {
- _debug("- retire object OBJ%x", object->fscache.debug_id);
- cachefiles_begin_secure(cache, &saved_cred);
- cachefiles_delete_object(cache, object);
- cachefiles_end_secure(cache, saved_cred);
- }
-
- /* close the filesystem stuff attached to the object */
- if (object->backer != object->dentry)
- dput(object->backer);
- object->backer = NULL;
-
- /* note that the object is now inactive */
- if (test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)) {
- write_lock(&cache->active_lock);
- if (!test_and_clear_bit(CACHEFILES_OBJECT_ACTIVE,
- &object->flags))
- BUG();
- rb_erase(&object->active_node, &cache->active_nodes);
- wake_up_bit(&object->flags, CACHEFILES_OBJECT_ACTIVE);
- write_unlock(&cache->active_lock);
- }
-
- dput(object->dentry);
- object->dentry = NULL;
-
- _leave("");
-}
-
-/*
- * dispose of a reference to an object
- */
-static void cachefiles_put_object(struct fscache_object *_object)
-{
- struct cachefiles_object *object;
- struct fscache_cache *cache;
-
- ASSERT(_object);
-
- object = container_of(_object, struct cachefiles_object, fscache);
-
- _enter("{OBJ%x,%d}",
- object->fscache.debug_id, atomic_read(&object->usage));
-
-#ifdef CACHEFILES_DEBUG_SLAB
- ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
-#endif
-
- ASSERTIFCMP(object->fscache.parent,
- object->fscache.parent->n_children, >, 0);
-
- if (atomic_dec_and_test(&object->usage)) {
- _debug("- kill object OBJ%x", object->fscache.debug_id);
-
- ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags));
- ASSERTCMP(object->fscache.parent, ==, NULL);
- ASSERTCMP(object->backer, ==, NULL);
- ASSERTCMP(object->dentry, ==, NULL);
- ASSERTCMP(object->fscache.n_ops, ==, 0);
- ASSERTCMP(object->fscache.n_children, ==, 0);
-
- if (object->lookup_data) {
- kfree(object->lookup_data->key);
- kfree(object->lookup_data->auxdata);
- kfree(object->lookup_data);
- object->lookup_data = NULL;
- }
-
- cache = object->fscache.cache;
- fscache_object_destroy(&object->fscache);
- kmem_cache_free(cachefiles_object_jar, object);
- fscache_object_destroyed(cache);
- }
-
- _leave("");
-}
-
-/*
- * sync a cache
- */
-static void cachefiles_sync_cache(struct fscache_cache *_cache)
-{
- struct cachefiles_cache *cache;
- const struct cred *saved_cred;
- int ret;
-
- _enter("%p", _cache);
-
- cache = container_of(_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->mnt->mnt_sb->s_umount);
- ret = sync_filesystem(cache->mnt->mnt_sb);
- up_read(&cache->mnt->mnt_sb->s_umount);
- cachefiles_end_secure(cache, saved_cred);
-
- if (ret == -EIO)
- cachefiles_io_error(cache,
- "Attempt to sync backing fs superblock"
- " returned error %d",
- ret);
-}
-
-/*
- * notification the attributes on an object have changed
- * - called with reads/writes excluded by FS-Cache
- */
-static int cachefiles_attr_changed(struct fscache_object *_object)
-{
- struct cachefiles_object *object;
- struct cachefiles_cache *cache;
- const struct cred *saved_cred;
- struct iattr newattrs;
- uint64_t ni_size;
- loff_t oi_size;
- int ret;
-
- _object->cookie->def->get_attr(_object->cookie->netfs_data, &ni_size);
-
- _enter("{OBJ%x},[%llu]",
- _object->debug_id, (unsigned long long) ni_size);
-
- object = container_of(_object, struct cachefiles_object, fscache);
- cache = container_of(object->fscache.cache,
- struct cachefiles_cache, cache);
-
- if (ni_size == object->i_size)
- return 0;
-
- if (!object->backer)
- return -ENOBUFS;
-
- ASSERT(S_ISREG(object->backer->d_inode->i_mode));
-
- fscache_set_store_limit(&object->fscache, ni_size);
-
- oi_size = i_size_read(object->backer->d_inode);
- if (oi_size == ni_size)
- return 0;
-
- cachefiles_begin_secure(cache, &saved_cred);
- mutex_lock(&object->backer->d_inode->i_mutex);
-
- /* if there's an extension to a partial page at the end of the backing
- * file, we need to discard the partial page so that we pick up new
- * data after it */
- if (oi_size & ~PAGE_MASK && ni_size > oi_size) {
- _debug("discard tail %llx", oi_size);
- newattrs.ia_valid = ATTR_SIZE;
- newattrs.ia_size = oi_size & PAGE_MASK;
- ret = notify_change(object->backer, &newattrs);
- if (ret < 0)
- goto truncate_failed;
- }
-
- newattrs.ia_valid = ATTR_SIZE;
- newattrs.ia_size = ni_size;
- ret = notify_change(object->backer, &newattrs);
-
-truncate_failed:
- mutex_unlock(&object->backer->d_inode->i_mutex);
- cachefiles_end_secure(cache, saved_cred);
-
- if (ret == -EIO) {
- fscache_set_store_limit(&object->fscache, 0);
- cachefiles_io_error_obj(object, "Size set failed");
- ret = -ENOBUFS;
- }
-
- _leave(" = %d", ret);
- return ret;
-}
-
-/*
- * dissociate a cache from all the pages it was backing
- */
-static void cachefiles_dissociate_pages(struct fscache_cache *cache)
-{
- _enter("");
-}
-
-const struct fscache_cache_ops cachefiles_cache_ops = {
- .name = "cachefiles",
- .alloc_object = cachefiles_alloc_object,
- .lookup_object = cachefiles_lookup_object,
- .lookup_complete = cachefiles_lookup_complete,
- .grab_object = cachefiles_grab_object,
- .update_object = cachefiles_update_object,
- .drop_object = cachefiles_drop_object,
- .put_object = cachefiles_put_object,
- .sync_cache = cachefiles_sync_cache,
- .attr_changed = cachefiles_attr_changed,
- .read_or_alloc_page = cachefiles_read_or_alloc_page,
- .read_or_alloc_pages = cachefiles_read_or_alloc_pages,
- .allocate_page = cachefiles_allocate_page,
- .allocate_pages = cachefiles_allocate_pages,
- .write_page = cachefiles_write_page,
- .uncache_page = cachefiles_uncache_page,
- .dissociate_pages = cachefiles_dissociate_pages,
-};
diff --git a/ANDROID_3.4.5/fs/cachefiles/internal.h b/ANDROID_3.4.5/fs/cachefiles/internal.h
deleted file mode 100644
index bd6bc1bd..00000000
--- a/ANDROID_3.4.5/fs/cachefiles/internal.h
+++ /dev/null
@@ -1,354 +0,0 @@
-/* General netfs cache on cache files internal defs
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#include <linux/fscache-cache.h>
-#include <linux/timer.h>
-#include <linux/wait.h>
-#include <linux/workqueue.h>
-#include <linux/security.h>
-
-struct cachefiles_cache;
-struct cachefiles_object;
-
-extern unsigned cachefiles_debug;
-#define CACHEFILES_DEBUG_KENTER 1
-#define CACHEFILES_DEBUG_KLEAVE 2
-#define CACHEFILES_DEBUG_KDEBUG 4
-
-/*
- * node records
- */
-struct cachefiles_object {
- struct fscache_object fscache; /* fscache handle */
- struct cachefiles_lookup_data *lookup_data; /* cached lookup data */
- struct dentry *dentry; /* the file/dir representing this object */
- struct dentry *backer; /* backing file */
- loff_t i_size; /* object size */
- unsigned long flags;
-#define CACHEFILES_OBJECT_ACTIVE 0 /* T if marked active */
-#define CACHEFILES_OBJECT_BURIED 1 /* T if preemptively buried */
- atomic_t usage; /* object usage count */
- uint8_t type; /* object type */
- uint8_t new; /* T if object new */
- spinlock_t work_lock;
- struct rb_node active_node; /* link in active tree (dentry is key) */
-};
-
-extern struct kmem_cache *cachefiles_object_jar;
-
-/*
- * Cache files cache definition
- */
-struct cachefiles_cache {
- struct fscache_cache cache; /* FS-Cache record */
- struct vfsmount *mnt; /* mountpoint holding the cache */
- struct dentry *graveyard; /* directory into which dead objects go */
- struct file *cachefilesd; /* manager daemon handle */
- const struct cred *cache_cred; /* security override for accessing cache */
- struct mutex daemon_mutex; /* command serialisation mutex */
- wait_queue_head_t daemon_pollwq; /* poll waitqueue for daemon */
- struct rb_root active_nodes; /* active nodes (can't be culled) */
- rwlock_t active_lock; /* lock for active_nodes */
- atomic_t gravecounter; /* graveyard uniquifier */
- unsigned frun_percent; /* when to stop culling (% files) */
- unsigned fcull_percent; /* when to start culling (% files) */
- unsigned fstop_percent; /* when to stop allocating (% files) */
- unsigned brun_percent; /* when to stop culling (% blocks) */
- unsigned bcull_percent; /* when to start culling (% blocks) */
- unsigned bstop_percent; /* when to stop allocating (% blocks) */
- unsigned bsize; /* cache's block size */
- unsigned bshift; /* min(ilog2(PAGE_SIZE / bsize), 0) */
- uint64_t frun; /* when to stop culling */
- uint64_t fcull; /* when to start culling */
- uint64_t fstop; /* when to stop allocating */
- sector_t brun; /* when to stop culling */
- sector_t bcull; /* when to start culling */
- sector_t bstop; /* when to stop allocating */
- unsigned long flags;
-#define CACHEFILES_READY 0 /* T if cache prepared */
-#define CACHEFILES_DEAD 1 /* T if cache dead */
-#define CACHEFILES_CULLING 2 /* T if cull engaged */
-#define CACHEFILES_STATE_CHANGED 3 /* T if state changed (poll trigger) */
- char *rootdirname; /* name of cache root directory */
- char *secctx; /* LSM security context */
- char *tag; /* cache binding tag */
-};
-
-/*
- * backing file read tracking
- */
-struct cachefiles_one_read {
- wait_queue_t monitor; /* link into monitored waitqueue */
- struct page *back_page; /* backing file page we're waiting for */
- struct page *netfs_page; /* netfs page we're going to fill */
- struct fscache_retrieval *op; /* retrieval op covering this */
- struct list_head op_link; /* link in op's todo list */
-};
-
-/*
- * backing file write tracking
- */
-struct cachefiles_one_write {
- struct page *netfs_page; /* netfs page to copy */
- struct cachefiles_object *object;
- struct list_head obj_link; /* link in object's lists */
- fscache_rw_complete_t end_io_func;
- void *context;
-};
-
-/*
- * auxiliary data xattr buffer
- */
-struct cachefiles_xattr {
- uint16_t len;
- uint8_t type;
- uint8_t data[];
-};
-
-/*
- * note change of state for daemon
- */
-static inline void cachefiles_state_changed(struct cachefiles_cache *cache)
-{
- set_bit(CACHEFILES_STATE_CHANGED, &cache->flags);
- wake_up_all(&cache->daemon_pollwq);
-}
-
-/*
- * bind.c
- */
-extern int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args);
-extern void cachefiles_daemon_unbind(struct cachefiles_cache *cache);
-
-/*
- * daemon.c
- */
-extern const struct file_operations cachefiles_daemon_fops;
-
-extern int cachefiles_has_space(struct cachefiles_cache *cache,
- unsigned fnr, unsigned bnr);
-
-/*
- * interface.c
- */
-extern const struct fscache_cache_ops cachefiles_cache_ops;
-
-/*
- * key.c
- */
-extern char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type);
-
-/*
- * namei.c
- */
-extern int cachefiles_delete_object(struct cachefiles_cache *cache,
- struct cachefiles_object *object);
-extern int cachefiles_walk_to_object(struct cachefiles_object *parent,
- struct cachefiles_object *object,
- const char *key,
- struct cachefiles_xattr *auxdata);
-extern struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
- struct dentry *dir,
- const char *name);
-
-extern int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
- char *filename);
-
-extern int cachefiles_check_in_use(struct cachefiles_cache *cache,
- struct dentry *dir, char *filename);
-
-/*
- * proc.c
- */
-#ifdef CONFIG_CACHEFILES_HISTOGRAM
-extern atomic_t cachefiles_lookup_histogram[HZ];
-extern atomic_t cachefiles_mkdir_histogram[HZ];
-extern atomic_t cachefiles_create_histogram[HZ];
-
-extern int __init cachefiles_proc_init(void);
-extern void cachefiles_proc_cleanup(void);
-static inline
-void cachefiles_hist(atomic_t histogram[], unsigned long start_jif)
-{
- unsigned long jif = jiffies - start_jif;
- if (jif >= HZ)
- jif = HZ - 1;
- atomic_inc(&histogram[jif]);
-}
-
-#else
-#define cachefiles_proc_init() (0)
-#define cachefiles_proc_cleanup() do {} while (0)
-#define cachefiles_hist(hist, start_jif) do {} while (0)
-#endif
-
-/*
- * rdwr.c
- */
-extern int cachefiles_read_or_alloc_page(struct fscache_retrieval *,
- struct page *, gfp_t);
-extern int cachefiles_read_or_alloc_pages(struct fscache_retrieval *,
- struct list_head *, unsigned *,
- gfp_t);
-extern int cachefiles_allocate_page(struct fscache_retrieval *, struct page *,
- gfp_t);
-extern int cachefiles_allocate_pages(struct fscache_retrieval *,
- struct list_head *, unsigned *, gfp_t);
-extern int cachefiles_write_page(struct fscache_storage *, struct page *);
-extern void cachefiles_uncache_page(struct fscache_object *, struct page *);
-
-/*
- * security.c
- */
-extern int cachefiles_get_security_ID(struct cachefiles_cache *cache);
-extern int cachefiles_determine_cache_security(struct cachefiles_cache *cache,
- struct dentry *root,
- const struct cred **_saved_cred);
-
-static inline void cachefiles_begin_secure(struct cachefiles_cache *cache,
- const struct cred **_saved_cred)
-{
- *_saved_cred = override_creds(cache->cache_cred);
-}
-
-static inline void cachefiles_end_secure(struct cachefiles_cache *cache,
- const struct cred *saved_cred)
-{
- revert_creds(saved_cred);
-}
-
-/*
- * xattr.c
- */
-extern int cachefiles_check_object_type(struct cachefiles_object *object);
-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_object_xattr(struct cachefiles_object *object,
- struct cachefiles_xattr *auxdata);
-extern int cachefiles_remove_object_xattr(struct cachefiles_cache *cache,
- struct dentry *dentry);
-
-
-/*
- * 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__); \
- fscache_io_error(&(___cache)->cache); \
- set_bit(CACHEFILES_DEAD, &(___cache)->flags); \
-} while (0)
-
-#define cachefiles_io_error_obj(object, FMT, ...) \
-do { \
- struct cachefiles_cache *___cache; \
- \
- ___cache = container_of((object)->fscache.cache, \
- struct cachefiles_cache, cache); \
- cachefiles_io_error(___cache, FMT, ##__VA_ARGS__); \
-} while (0)
-
-
-/*
- * debug tracing
- */
-#define dbgprintk(FMT, ...) \
- printk(KERN_DEBUG "[%-6.6s] "FMT"\n", current->comm, ##__VA_ARGS__)
-
-#define kenter(FMT, ...) dbgprintk("==> %s("FMT")", __func__, ##__VA_ARGS__)
-#define kleave(FMT, ...) dbgprintk("<== %s()"FMT"", __func__, ##__VA_ARGS__)
-#define kdebug(FMT, ...) dbgprintk(FMT, ##__VA_ARGS__)
-
-
-#if defined(__KDEBUG)
-#define _enter(FMT, ...) kenter(FMT, ##__VA_ARGS__)
-#define _leave(FMT, ...) kleave(FMT, ##__VA_ARGS__)
-#define _debug(FMT, ...) kdebug(FMT, ##__VA_ARGS__)
-
-#elif defined(CONFIG_CACHEFILES_DEBUG)
-#define _enter(FMT, ...) \
-do { \
- if (cachefiles_debug & CACHEFILES_DEBUG_KENTER) \
- kenter(FMT, ##__VA_ARGS__); \
-} while (0)
-
-#define _leave(FMT, ...) \
-do { \
- if (cachefiles_debug & CACHEFILES_DEBUG_KLEAVE) \
- kleave(FMT, ##__VA_ARGS__); \
-} while (0)
-
-#define _debug(FMT, ...) \
-do { \
- if (cachefiles_debug & CACHEFILES_DEBUG_KDEBUG) \
- kdebug(FMT, ##__VA_ARGS__); \
-} while (0)
-
-#else
-#define _enter(FMT, ...) no_printk("==> %s("FMT")", __func__, ##__VA_ARGS__)
-#define _leave(FMT, ...) no_printk("<== %s()"FMT"", __func__, ##__VA_ARGS__)
-#define _debug(FMT, ...) no_printk(FMT, ##__VA_ARGS__)
-#endif
-
-#if 1 /* defined(__KDEBUGALL) */
-
-#define ASSERT(X) \
-do { \
- if (unlikely(!(X))) { \
- printk(KERN_ERR "\n"); \
- printk(KERN_ERR "CacheFiles: Assertion failed\n"); \
- BUG(); \
- } \
-} while (0)
-
-#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", \
- (unsigned long)(X), (unsigned long)(Y)); \
- BUG(); \
- } \
-} while (0)
-
-#define ASSERTIF(C, X) \
-do { \
- if (unlikely((C) && !(X))) { \
- printk(KERN_ERR "\n"); \
- printk(KERN_ERR "CacheFiles: Assertion failed\n"); \
- BUG(); \
- } \
-} while (0)
-
-#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", \
- (unsigned long)(X), (unsigned long)(Y)); \
- BUG(); \
- } \
-} while (0)
-
-#else
-
-#define ASSERT(X) do {} while (0)
-#define ASSERTCMP(X, OP, Y) do {} while (0)
-#define ASSERTIF(C, X) do {} while (0)
-#define ASSERTIFCMP(C, X, OP, Y) do {} while (0)
-
-#endif
diff --git a/ANDROID_3.4.5/fs/cachefiles/key.c b/ANDROID_3.4.5/fs/cachefiles/key.c
deleted file mode 100644
index 81b8b2b3..00000000
--- a/ANDROID_3.4.5/fs/cachefiles/key.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/* Key to pathname encoder
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#include <linux/slab.h>
-#include "internal.h"
-
-static const char cachefiles_charmap[64] =
- "0123456789" /* 0 - 9 */
- "abcdefghijklmnopqrstuvwxyz" /* 10 - 35 */
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* 36 - 61 */
- "_-" /* 62 - 63 */
- ;
-
-static const char cachefiles_filecharmap[256] = {
- /* we skip space and tab and control chars */
- [33 ... 46] = 1, /* '!' -> '.' */
- /* we skip '/' as it's significant to pathwalk */
- [48 ... 127] = 1, /* '0' -> '~' */
-};
-
-/*
- * turn the raw key into something cooked
- * - the raw key should include the length in the two bytes at the front
- * - the key may be up to 514 bytes in length (including the length word)
- * - "base64" encode the strange keys, mapping 3 bytes of raw to four of
- * cooked
- * - need to cut the cooked key into 252 char lengths (189 raw bytes)
- */
-char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type)
-{
- unsigned char csum, ch;
- unsigned int acc;
- char *key;
- int loop, len, max, seg, mark, print;
-
- _enter(",%d", keylen);
-
- BUG_ON(keylen < 2 || keylen > 514);
-
- csum = raw[0] + raw[1];
- print = 1;
- for (loop = 2; loop < keylen; loop++) {
- ch = raw[loop];
- csum += ch;
- print &= cachefiles_filecharmap[ch];
- }
-
- if (print) {
- /* if the path is usable ASCII, then we render it directly */
- max = keylen - 2;
- max += 2; /* two base64'd length chars on the front */
- max += 5; /* @checksum/M */
- max += 3 * 2; /* maximum number of segment dividers (".../M")
- * is ((514 + 251) / 252) = 3
- */
- max += 1; /* NUL on end */
- } else {
- /* calculate the maximum length of the cooked key */
- keylen = (keylen + 2) / 3;
-
- max = keylen * 4;
- max += 5; /* @checksum/M */
- max += 3 * 2; /* maximum number of segment dividers (".../M")
- * is ((514 + 188) / 189) = 3
- */
- max += 1; /* NUL on end */
- }
-
- max += 1; /* 2nd NUL on end */
-
- _debug("max: %d", max);
-
- key = kmalloc(max, GFP_KERNEL);
- if (!key)
- return NULL;
-
- len = 0;
-
- /* build the cooked key */
- sprintf(key, "@%02x%c+", (unsigned) csum, 0);
- len = 5;
- mark = len - 1;
-
- if (print) {
- acc = *(uint16_t *) raw;
- raw += 2;
-
- key[len + 1] = cachefiles_charmap[acc & 63];
- acc >>= 6;
- key[len] = cachefiles_charmap[acc & 63];
- len += 2;
-
- seg = 250;
- for (loop = keylen; loop > 0; loop--) {
- if (seg <= 0) {
- key[len++] = '\0';
- mark = len;
- key[len++] = '+';
- seg = 252;
- }
-
- key[len++] = *raw++;
- ASSERT(len < max);
- }
-
- switch (type) {
- case FSCACHE_COOKIE_TYPE_INDEX: type = 'I'; break;
- case FSCACHE_COOKIE_TYPE_DATAFILE: type = 'D'; break;
- default: type = 'S'; break;
- }
- } else {
- seg = 252;
- for (loop = keylen; loop > 0; loop--) {
- if (seg <= 0) {
- key[len++] = '\0';
- mark = len;
- key[len++] = '+';
- seg = 252;
- }
-
- acc = *raw++;
- acc |= *raw++ << 8;
- acc |= *raw++ << 16;
-
- _debug("acc: %06x", acc);
-
- key[len++] = cachefiles_charmap[acc & 63];
- acc >>= 6;
- key[len++] = cachefiles_charmap[acc & 63];
- acc >>= 6;
- key[len++] = cachefiles_charmap[acc & 63];
- acc >>= 6;
- key[len++] = cachefiles_charmap[acc & 63];
-
- ASSERT(len < max);
- }
-
- switch (type) {
- case FSCACHE_COOKIE_TYPE_INDEX: type = 'J'; break;
- case FSCACHE_COOKIE_TYPE_DATAFILE: type = 'E'; break;
- default: type = 'T'; break;
- }
- }
-
- key[mark] = type;
- key[len++] = 0;
- key[len] = 0;
-
- _leave(" = %p %d", key, len);
- return key;
-}
diff --git a/ANDROID_3.4.5/fs/cachefiles/main.c b/ANDROID_3.4.5/fs/cachefiles/main.c
deleted file mode 100644
index 4bfa8cf4..00000000
--- a/ANDROID_3.4.5/fs/cachefiles/main.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/* Network filesystem caching backend to use cache files on a premounted
- * filesystem
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#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/sysctl.h>
-#include <linux/miscdevice.h>
-#include "internal.h"
-
-unsigned cachefiles_debug;
-module_param_named(debug, cachefiles_debug, uint, S_IWUSR | S_IRUGO);
-MODULE_PARM_DESC(cachefiles_debug, "CacheFiles debugging mask");
-
-MODULE_DESCRIPTION("Mounted-filesystem based cache");
-MODULE_AUTHOR("Red Hat, Inc.");
-MODULE_LICENSE("GPL");
-
-struct kmem_cache *cachefiles_object_jar;
-
-static struct miscdevice cachefiles_dev = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "cachefiles",
- .fops = &cachefiles_daemon_fops,
-};
-
-static void cachefiles_object_init_once(void *_object)
-{
- struct cachefiles_object *object = _object;
-
- memset(object, 0, sizeof(*object));
- spin_lock_init(&object->work_lock);
-}
-
-/*
- * initialise the fs caching module
- */
-static int __init cachefiles_init(void)
-{
- int ret;
-
- ret = misc_register(&cachefiles_dev);
- if (ret < 0)
- goto error_dev;
-
- /* create an object jar */
- ret = -ENOMEM;
- cachefiles_object_jar =
- kmem_cache_create("cachefiles_object_jar",
- sizeof(struct cachefiles_object),
- 0,
- SLAB_HWCACHE_ALIGN,
- cachefiles_object_init_once);
- if (!cachefiles_object_jar) {
- printk(KERN_NOTICE
- "CacheFiles: Failed to allocate an object jar\n");
- goto error_object_jar;
- }
-
- ret = cachefiles_proc_init();
- if (ret < 0)
- goto error_proc;
-
- printk(KERN_INFO "CacheFiles: Loaded\n");
- return 0;
-
-error_proc:
- kmem_cache_destroy(cachefiles_object_jar);
-error_object_jar:
- misc_deregister(&cachefiles_dev);
-error_dev:
- kerror("failed to register: %d", ret);
- return ret;
-}
-
-fs_initcall(cachefiles_init);
-
-/*
- * clean up on module removal
- */
-static void __exit cachefiles_exit(void)
-{
- printk(KERN_INFO "CacheFiles: Unloading\n");
-
- cachefiles_proc_cleanup();
- kmem_cache_destroy(cachefiles_object_jar);
- misc_deregister(&cachefiles_dev);
-}
-
-module_exit(cachefiles_exit);
diff --git a/ANDROID_3.4.5/fs/cachefiles/namei.c b/ANDROID_3.4.5/fs/cachefiles/namei.c
deleted file mode 100644
index 7f0771d3..00000000
--- a/ANDROID_3.4.5/fs/cachefiles/namei.c
+++ /dev/null
@@ -1,989 +0,0 @@
-/* CacheFiles path walking and related routines
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/fsnotify.h>
-#include <linux/quotaops.h>
-#include <linux/xattr.h>
-#include <linux/mount.h>
-#include <linux/namei.h>
-#include <linux/security.h>
-#include <linux/slab.h>
-#include "internal.h"
-
-#define CACHEFILES_KEYBUF_SIZE 512
-
-/*
- * dump debugging info about an object
- */
-static noinline
-void __cachefiles_printk_object(struct cachefiles_object *object,
- const char *prefix,
- u8 *keybuf)
-{
- 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],
- 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",
- prefix, object->fscache.n_ops, object->fscache.n_in_progress,
- object->fscache.n_exclusive);
- printk(KERN_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",
- prefix,
- object->fscache.cookie,
- object->fscache.cookie->parent,
- object->fscache.cookie->netfs_data,
- object->fscache.cookie->flags);
- if (keybuf)
- keylen = cookie->def->get_key(cookie->netfs_data, keybuf,
- CACHEFILES_KEYBUF_SIZE);
- else
- keylen = 0;
- } else {
- printk(KERN_ERR "%scookie=NULL\n", prefix);
- keylen = 0;
- }
- spin_unlock(&object->fscache.lock);
-
- if (keylen) {
- printk(KERN_ERR "%skey=[%u] '", prefix, keylen);
- for (loop = 0; loop < keylen; loop++)
- printk("%02x", keybuf[loop]);
- printk("'\n");
- }
-}
-
-/*
- * dump debugging info about a pair of objects
- */
-static noinline void cachefiles_printk_object(struct cachefiles_object *object,
- struct cachefiles_object *xobject)
-{
- u8 *keybuf;
-
- keybuf = kmalloc(CACHEFILES_KEYBUF_SIZE, GFP_NOIO);
- if (object)
- __cachefiles_printk_object(object, "", keybuf);
- if (xobject)
- __cachefiles_printk_object(xobject, "x", keybuf);
- kfree(keybuf);
-}
-
-/*
- * mark the owner of a dentry, if there is one, to indicate that that dentry
- * has been preemptively deleted
- * - the caller must hold the i_mutex on the dentry's parent as required to
- * call vfs_unlink(), vfs_rmdir() or vfs_rename()
- */
-static void cachefiles_mark_object_buried(struct cachefiles_cache *cache,
- struct dentry *dentry)
-{
- struct cachefiles_object *object;
- struct rb_node *p;
-
- _enter(",'%*.*s'",
- dentry->d_name.len, dentry->d_name.len, dentry->d_name.name);
-
- write_lock(&cache->active_lock);
-
- p = cache->active_nodes.rb_node;
- while (p) {
- object = rb_entry(p, struct cachefiles_object, active_node);
- if (object->dentry > dentry)
- p = p->rb_left;
- else if (object->dentry < dentry)
- p = p->rb_right;
- else
- goto found_dentry;
- }
-
- write_unlock(&cache->active_lock);
- _leave(" [no owner]");
- return;
-
- /* found the dentry for */
-found_dentry:
- kdebug("preemptive burial: OBJ%x [%s] %p",
- object->fscache.debug_id,
- fscache_object_states[object->fscache.state],
- dentry);
-
- if (object->fscache.state < FSCACHE_OBJECT_DYING) {
- printk(KERN_ERR "\n");
- printk(KERN_ERR "CacheFiles: 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");
- }
-
- write_unlock(&cache->active_lock);
- _leave(" [owner marked]");
-}
-
-/*
- * record the fact that an object is now active
- */
-static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
- struct cachefiles_object *object)
-{
- struct cachefiles_object *xobject;
- struct rb_node **_p, *_parent = NULL;
- struct dentry *dentry;
-
- _enter(",%p", object);
-
-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");
- cachefiles_printk_object(object, NULL);
- BUG();
- }
-
- dentry = object->dentry;
- _p = &cache->active_nodes.rb_node;
- while (*_p) {
- _parent = *_p;
- xobject = rb_entry(_parent,
- struct cachefiles_object, active_node);
-
- ASSERT(xobject != object);
-
- if (xobject->dentry > dentry)
- _p = &(*_p)->rb_left;
- else if (xobject->dentry < dentry)
- _p = &(*_p)->rb_right;
- else
- goto wait_for_old_object;
- }
-
- rb_link_node(&object->active_node, _parent, _p);
- rb_insert_color(&object->active_node, &cache->active_nodes);
-
- write_unlock(&cache->active_lock);
- _leave(" = 0");
- return 0;
-
- /* 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");
- cachefiles_printk_object(object, xobject);
- BUG();
- }
- atomic_inc(&xobject->usage);
- write_unlock(&cache->active_lock);
-
- if (test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags)) {
- wait_queue_head_t *wq;
-
- signed long timeout = 60 * HZ;
- wait_queue_t wait;
- bool requeue;
-
- /* if the object we're waiting for is queued for processing,
- * then just put ourselves on the queue behind it */
- if (work_pending(&xobject->fscache.work)) {
- _debug("queue OBJ%x behind OBJ%x immediately",
- object->fscache.debug_id,
- xobject->fscache.debug_id);
- goto requeue;
- }
-
- /* otherwise we sleep until either the object we're waiting for
- * is done, or the fscache_object is congested */
- wq = bit_waitqueue(&xobject->flags, CACHEFILES_OBJECT_ACTIVE);
- init_wait(&wait);
- requeue = false;
- do {
- prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
- if (!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags))
- break;
-
- requeue = fscache_object_sleep_till_congested(&timeout);
- } while (timeout > 0 && !requeue);
- finish_wait(wq, &wait);
-
- if (requeue &&
- test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags)) {
- _debug("queue OBJ%x behind OBJ%x after wait",
- object->fscache.debug_id,
- xobject->fscache.debug_id);
- goto requeue;
- }
-
- if (timeout <= 0) {
- printk(KERN_ERR "\n");
- printk(KERN_ERR "CacheFiles: Error: Overlong"
- " wait for old active object to go away\n");
- cachefiles_printk_object(object, xobject);
- goto requeue;
- }
- }
-
- ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags));
-
- cache->cache.ops->put_object(&xobject->fscache);
- goto try_again;
-
-requeue:
- clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
- cache->cache.ops->put_object(&xobject->fscache);
- _leave(" = -ETIMEDOUT");
- return -ETIMEDOUT;
-}
-
-/*
- * delete an object representation from the cache
- * - file backed objects are unlinked
- * - directory backed objects are stuffed into the graveyard for userspace to
- * delete
- * - unlocks the directory mutex
- */
-static int cachefiles_bury_object(struct cachefiles_cache *cache,
- struct dentry *dir,
- struct dentry *rep,
- bool preemptive)
-{
- struct dentry *grave, *trap;
- struct path path, path_to_graveyard;
- char nbuffer[8 + 8 + 1];
- int ret;
-
- _enter(",'%*.*s','%*.*s'",
- dir->d_name.len, dir->d_name.len, dir->d_name.name,
- rep->d_name.len, rep->d_name.len, rep->d_name.name);
-
- _debug("remove %p from %p", rep, dir);
-
- /* non-directories can just be unlinked */
- if (!S_ISDIR(rep->d_inode->i_mode)) {
- _debug("unlink stale object");
-
- 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);
-
- if (preemptive)
- cachefiles_mark_object_buried(cache, rep);
- }
-
- mutex_unlock(&dir->d_inode->i_mutex);
-
- if (ret == -EIO)
- cachefiles_io_error(cache, "Unlink failed");
-
- _leave(" = %d", ret);
- return ret;
- }
-
- /* directories have to be moved to the graveyard */
- _debug("move stale object to graveyard");
- mutex_unlock(&dir->d_inode->i_mutex);
-
-try_again:
- /* first step is to make up a grave dentry in the graveyard */
- sprintf(nbuffer, "%08x%08x",
- (uint32_t) get_seconds(),
- (uint32_t) atomic_inc_return(&cache->gravecounter));
-
- /* do the multiway lock magic */
- trap = lock_rename(cache->graveyard, dir);
-
- /* do some checks before getting the grave dentry */
- if (rep->d_parent != dir) {
- /* the entry was probably culled when we dropped the parent dir
- * lock */
- unlock_rename(cache->graveyard, dir);
- _leave(" = 0 [culled?]");
- return 0;
- }
-
- if (!S_ISDIR(cache->graveyard->d_inode->i_mode)) {
- unlock_rename(cache->graveyard, dir);
- cachefiles_io_error(cache, "Graveyard no longer a directory");
- return -EIO;
- }
-
- if (trap == rep) {
- unlock_rename(cache->graveyard, dir);
- cachefiles_io_error(cache, "May not make directory loop");
- return -EIO;
- }
-
- if (d_mountpoint(rep)) {
- unlock_rename(cache->graveyard, dir);
- cachefiles_io_error(cache, "Mountpoint in cache");
- return -EIO;
- }
-
- grave = lookup_one_len(nbuffer, cache->graveyard, strlen(nbuffer));
- if (IS_ERR(grave)) {
- unlock_rename(cache->graveyard, dir);
-
- if (PTR_ERR(grave) == -ENOMEM) {
- _leave(" = -ENOMEM");
- return -ENOMEM;
- }
-
- cachefiles_io_error(cache, "Lookup error %ld",
- PTR_ERR(grave));
- return -EIO;
- }
-
- if (grave->d_inode) {
- unlock_rename(cache->graveyard, dir);
- dput(grave);
- grave = NULL;
- cond_resched();
- goto try_again;
- }
-
- if (d_mountpoint(grave)) {
- unlock_rename(cache->graveyard, dir);
- dput(grave);
- cachefiles_io_error(cache, "Mountpoint in graveyard");
- return -EIO;
- }
-
- /* target should not be an ancestor of source */
- if (trap == grave) {
- unlock_rename(cache->graveyard, dir);
- dput(grave);
- cachefiles_io_error(cache, "May not make directory loop");
- return -EIO;
- }
-
- /* attempt the rename */
- 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);
- 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);
- if (ret != 0 && ret != -ENOMEM)
- cachefiles_io_error(cache,
- "Rename failed with error %d", ret);
-
- if (preemptive)
- cachefiles_mark_object_buried(cache, rep);
- }
-
- unlock_rename(cache->graveyard, dir);
- dput(grave);
- _leave(" = 0");
- return 0;
-}
-
-/*
- * delete an object representation from the cache
- */
-int cachefiles_delete_object(struct cachefiles_cache *cache,
- struct cachefiles_object *object)
-{
- struct dentry *dir;
- int ret;
-
- _enter(",OBJ%x{%p}", object->fscache.debug_id, object->dentry);
-
- ASSERT(object->dentry);
- ASSERT(object->dentry->d_inode);
- ASSERT(object->dentry->d_parent);
-
- dir = dget_parent(object->dentry);
-
- mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
-
- if (test_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) {
- /* object allocation for the same key preemptively deleted this
- * object's file so that it could create its own file */
- _debug("object preemptively buried");
- mutex_unlock(&dir->d_inode->i_mutex);
- ret = 0;
- } else {
- /* we need to check that our parent is _still_ our parent - it
- * may have been renamed */
- if (dir == object->dentry->d_parent) {
- ret = cachefiles_bury_object(cache, dir,
- object->dentry, false);
- } else {
- /* it got moved, presumably by cachefilesd culling it,
- * so it's no longer in the key path and we can ignore
- * it */
- mutex_unlock(&dir->d_inode->i_mutex);
- ret = 0;
- }
- }
-
- dput(dir);
- _leave(" = %d", ret);
- return ret;
-}
-
-/*
- * walk from the parent object to the child object through the backing
- * filesystem, creating directories as we go
- */
-int cachefiles_walk_to_object(struct cachefiles_object *parent,
- struct cachefiles_object *object,
- const char *key,
- struct cachefiles_xattr *auxdata)
-{
- struct cachefiles_cache *cache;
- struct dentry *dir, *next = NULL;
- struct path path;
- unsigned long start;
- const char *name;
- int ret, nlen;
-
- _enter("OBJ%x{%p},OBJ%x,%s,",
- parent->fscache.debug_id, parent->dentry,
- object->fscache.debug_id, key);
-
- cache = container_of(parent->fscache.cache,
- struct cachefiles_cache, cache);
- path.mnt = cache->mnt;
-
- ASSERT(parent->dentry);
- ASSERT(parent->dentry->d_inode);
-
- if (!(S_ISDIR(parent->dentry->d_inode->i_mode))) {
- // TODO: convert file to dir
- _leave("looking up in none directory");
- return -ENOBUFS;
- }
-
- dir = dget(parent->dentry);
-
-advance:
- /* attempt to transit the first directory component */
- name = key;
- nlen = strlen(key);
-
- /* key ends in a double NUL */
- key = key + nlen + 1;
- if (!*key)
- key = NULL;
-
-lookup_again:
- /* search the current directory for the element name */
- _debug("lookup '%s'", name);
-
- mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
-
- start = jiffies;
- next = lookup_one_len(name, dir, nlen);
- cachefiles_hist(cachefiles_lookup_histogram, start);
- if (IS_ERR(next))
- goto lookup_error;
-
- _debug("next -> %p %s", next, next->d_inode ? "positive" : "negative");
-
- if (!key)
- object->new = !next->d_inode;
-
- /* if this element of the path doesn't exist, then the lookup phase
- * failed, and we can release any readers in the certain knowledge that
- * there's nothing for them to actually read */
- if (!next->d_inode)
- fscache_object_lookup_negative(&object->fscache);
-
- /* we need to create the object if it's negative */
- if (key || object->type == FSCACHE_COOKIE_TYPE_INDEX) {
- /* index objects and intervening tree levels must be subdirs */
- if (!next->d_inode) {
- ret = cachefiles_has_space(cache, 1, 0);
- 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);
- if (ret < 0)
- goto create_error;
-
- ASSERT(next->d_inode);
-
- _debug("mkdir -> %p{%p{ino=%lu}}",
- 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",
- next->d_inode->i_ino);
- ret = -ENOBUFS;
- goto error;
- }
-
- } else {
- /* non-index objects start out life as files */
- if (!next->d_inode) {
- ret = cachefiles_has_space(cache, 1, 0);
- 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);
- cachefiles_hist(cachefiles_create_histogram, start);
- if (ret < 0)
- goto create_error;
-
- ASSERT(next->d_inode);
-
- _debug("create -> %p{%p{ino=%lu}}",
- next, next->d_inode, next->d_inode->i_ino);
-
- } 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",
- next->d_inode->i_ino);
- ret = -ENOBUFS;
- goto error;
- }
- }
-
- /* process the next component */
- if (key) {
- _debug("advance");
- mutex_unlock(&dir->d_inode->i_mutex);
- dput(dir);
- dir = next;
- next = NULL;
- goto advance;
- }
-
- /* we've found the object we were looking for */
- object->dentry = next;
-
- /* if we've found that the terminal object exists, then we need to
- * check its attributes and delete it if it's out of date */
- if (!object->new) {
- _debug("validate '%*.*s'",
- next->d_name.len, next->d_name.len, next->d_name.name);
-
- ret = cachefiles_check_object_xattr(object, auxdata);
- if (ret == -ESTALE) {
- /* delete the object (the deleter drops the directory
- * mutex) */
- object->dentry = NULL;
-
- ret = cachefiles_bury_object(cache, dir, next, true);
- dput(next);
- next = NULL;
-
- if (ret < 0)
- goto delete_error;
-
- _debug("redo lookup");
- goto lookup_again;
- }
- }
-
- /* note that we're now using this object */
- ret = cachefiles_mark_object_active(cache, object);
-
- mutex_unlock(&dir->d_inode->i_mutex);
- dput(dir);
- dir = NULL;
-
- if (ret == -ETIMEDOUT)
- goto mark_active_timed_out;
-
- _debug("=== OBTAINED_OBJECT ===");
-
- if (object->new) {
- /* attach data to a newly constructed terminal object */
- ret = cachefiles_set_object_xattr(object, auxdata);
- if (ret < 0)
- goto check_error;
- } else {
- /* always update the atime on an object we've just looked up
- * (this is used to keep track of culling, and atimes are only
- * updated by read, write and readdir but not lookup or
- * open) */
- path.dentry = next;
- touch_atime(&path);
- }
-
- /* open a file interface onto a data file */
- if (object->type != FSCACHE_COOKIE_TYPE_INDEX) {
- if (S_ISREG(object->dentry->d_inode->i_mode)) {
- const struct address_space_operations *aops;
-
- ret = -EPERM;
- aops = object->dentry->d_inode->i_mapping->a_ops;
- if (!aops->bmap)
- goto check_error;
-
- object->backer = object->dentry;
- } else {
- BUG(); // TODO: open file in data-class subdir
- }
- }
-
- object->new = 0;
- fscache_obtained_object(&object->fscache);
-
- _leave(" = 0 [%lu]", object->dentry->d_inode->i_ino);
- return 0;
-
-create_error:
- _debug("create error %d", ret);
- if (ret == -EIO)
- cachefiles_io_error(cache, "Create/mkdir failed");
- goto error;
-
-mark_active_timed_out:
- _debug("mark active timed out");
- goto release_dentry;
-
-check_error:
- _debug("check error %d", ret);
- write_lock(&cache->active_lock);
- rb_erase(&object->active_node, &cache->active_nodes);
- clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
- wake_up_bit(&object->flags, CACHEFILES_OBJECT_ACTIVE);
- write_unlock(&cache->active_lock);
-release_dentry:
- dput(object->dentry);
- object->dentry = NULL;
- goto error_out;
-
-delete_error:
- _debug("delete error %d", ret);
- goto error_out2;
-
-lookup_error:
- _debug("lookup error %ld", PTR_ERR(next));
- ret = PTR_ERR(next);
- if (ret == -EIO)
- cachefiles_io_error(cache, "Lookup failed");
- next = NULL;
-error:
- mutex_unlock(&dir->d_inode->i_mutex);
- dput(next);
-error_out2:
- dput(dir);
-error_out:
- _leave(" = error %d", -ret);
- return ret;
-}
-
-/*
- * get a subdirectory
- */
-struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
- struct dentry *dir,
- const char *dirname)
-{
- struct dentry *subdir;
- unsigned long start;
- struct path path;
- int ret;
-
- _enter(",,%s", dirname);
-
- /* search the current directory for the element name */
- mutex_lock(&dir->d_inode->i_mutex);
-
- start = jiffies;
- subdir = lookup_one_len(dirname, dir, strlen(dirname));
- cachefiles_hist(cachefiles_lookup_histogram, start);
- if (IS_ERR(subdir)) {
- if (PTR_ERR(subdir) == -ENOMEM)
- goto nomem_d_alloc;
- goto lookup_error;
- }
-
- _debug("subdir -> %p %s",
- subdir, subdir->d_inode ? "positive" : "negative");
-
- /* we need to create the subdir if it doesn't exist yet */
- if (!subdir->d_inode) {
- ret = cachefiles_has_space(cache, 1, 0);
- if (ret < 0)
- goto mkdir_error;
-
- _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;
-
- ASSERT(subdir->d_inode);
-
- _debug("mkdir -> %p{%p{ino=%lu}}",
- subdir,
- subdir->d_inode,
- subdir->d_inode->i_ino);
- }
-
- mutex_unlock(&dir->d_inode->i_mutex);
-
- /* we need to make sure the subdir is a directory */
- ASSERT(subdir->d_inode);
-
- if (!S_ISDIR(subdir->d_inode->i_mode)) {
- kerror("%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 ||
- !subdir->d_inode->i_op->getxattr ||
- !subdir->d_inode->i_op->lookup ||
- !subdir->d_inode->i_op->mkdir ||
- !subdir->d_inode->i_op->create ||
- !subdir->d_inode->i_op->rename ||
- !subdir->d_inode->i_op->rmdir ||
- !subdir->d_inode->i_op->unlink)
- goto check_error;
-
- _leave(" = [%lu]", subdir->d_inode->i_ino);
- return subdir;
-
-check_error:
- dput(subdir);
- _leave(" = %d [check]", ret);
- return ERR_PTR(ret);
-
-mkdir_error:
- mutex_unlock(&dir->d_inode->i_mutex);
- dput(subdir);
- kerror("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);
- return ERR_PTR(ret);
-
-nomem_d_alloc:
- mutex_unlock(&dir->d_inode->i_mutex);
- _leave(" = -ENOMEM");
- return ERR_PTR(-ENOMEM);
-}
-
-/*
- * find out if an object is in use or not
- * - if finds object and it's not in use:
- * - returns a pointer to the object and a reference on it
- * - returns with the directory locked
- */
-static struct dentry *cachefiles_check_active(struct cachefiles_cache *cache,
- struct dentry *dir,
- char *filename)
-{
- struct cachefiles_object *object;
- struct rb_node *_n;
- struct dentry *victim;
- unsigned long start;
- int ret;
-
- //_enter(",%*.*s/,%s",
- // 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);
-
- start = jiffies;
- victim = lookup_one_len(filename, dir, strlen(filename));
- cachefiles_hist(cachefiles_lookup_histogram, start);
- if (IS_ERR(victim))
- goto lookup_error;
-
- //_debug("victim -> %p %s",
- // victim, victim->d_inode ? "positive" : "negative");
-
- /* if the object is no longer there then we probably retired the object
- * at the netfs's request whilst the cull was in progress
- */
- if (!victim->d_inode) {
- mutex_unlock(&dir->d_inode->i_mutex);
- dput(victim);
- _leave(" = -ENOENT [absent]");
- return ERR_PTR(-ENOENT);
- }
-
- /* check to see if we're using this object */
- read_lock(&cache->active_lock);
-
- _n = cache->active_nodes.rb_node;
-
- while (_n) {
- object = rb_entry(_n, struct cachefiles_object, active_node);
-
- if (object->dentry > victim)
- _n = _n->rb_left;
- else if (object->dentry < victim)
- _n = _n->rb_right;
- else
- goto object_in_use;
- }
-
- read_unlock(&cache->active_lock);
-
- //_leave(" = %p", victim);
- return victim;
-
-object_in_use:
- read_unlock(&cache->active_lock);
- mutex_unlock(&dir->d_inode->i_mutex);
- dput(victim);
- //_leave(" = -EBUSY [in use]");
- return ERR_PTR(-EBUSY);
-
-lookup_error:
- mutex_unlock(&dir->d_inode->i_mutex);
- ret = PTR_ERR(victim);
- if (ret == -ENOENT) {
- /* file or dir now absent - probably retired by netfs */
- _leave(" = -ESTALE [absent]");
- return ERR_PTR(-ESTALE);
- }
-
- if (ret == -EIO) {
- cachefiles_io_error(cache, "Lookup failed");
- } else if (ret != -ENOMEM) {
- kerror("Internal error: %d", ret);
- ret = -EIO;
- }
-
- _leave(" = %d", ret);
- return ERR_PTR(ret);
-}
-
-/*
- * cull an object if it's not in use
- * - called only by cache manager daemon
- */
-int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
- char *filename)
-{
- struct dentry *victim;
- int ret;
-
- _enter(",%*.*s/,%s",
- dir->d_name.len, dir->d_name.len, dir->d_name.name, filename);
-
- victim = cachefiles_check_active(cache, dir, filename);
- if (IS_ERR(victim))
- return PTR_ERR(victim);
-
- _debug("victim -> %p %s",
- victim, victim->d_inode ? "positive" : "negative");
-
- /* okay... the victim is not being used so we can cull it
- * - start by marking it as stale
- */
- _debug("victim is cullable");
-
- ret = cachefiles_remove_object_xattr(cache, victim);
- if (ret < 0)
- goto error_unlock;
-
- /* actually remove the victim (drops the dir mutex) */
- _debug("bury");
-
- ret = cachefiles_bury_object(cache, dir, victim, false);
- if (ret < 0)
- goto error;
-
- dput(victim);
- _leave(" = 0");
- return 0;
-
-error_unlock:
- mutex_unlock(&dir->d_inode->i_mutex);
-error:
- dput(victim);
- if (ret == -ENOENT) {
- /* file or dir now absent - probably retired by netfs */
- _leave(" = -ESTALE [absent]");
- return -ESTALE;
- }
-
- if (ret != -ENOMEM) {
- kerror("Internal error: %d", ret);
- ret = -EIO;
- }
-
- _leave(" = %d", ret);
- return ret;
-}
-
-/*
- * find out if an object is in use or not
- * - called only by cache manager daemon
- * - returns -EBUSY or 0 to indicate whether an object is in use or not
- */
-int cachefiles_check_in_use(struct cachefiles_cache *cache, struct dentry *dir,
- char *filename)
-{
- struct dentry *victim;
-
- //_enter(",%*.*s/,%s",
- // dir->d_name.len, dir->d_name.len, dir->d_name.name, filename);
-
- victim = cachefiles_check_active(cache, dir, filename);
- if (IS_ERR(victim))
- return PTR_ERR(victim);
-
- mutex_unlock(&dir->d_inode->i_mutex);
- dput(victim);
- //_leave(" = 0");
- return 0;
-}
diff --git a/ANDROID_3.4.5/fs/cachefiles/proc.c b/ANDROID_3.4.5/fs/cachefiles/proc.c
deleted file mode 100644
index eccd3394..00000000
--- a/ANDROID_3.4.5/fs/cachefiles/proc.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/* CacheFiles statistics
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include "internal.h"
-
-atomic_t cachefiles_lookup_histogram[HZ];
-atomic_t cachefiles_mkdir_histogram[HZ];
-atomic_t cachefiles_create_histogram[HZ];
-
-/*
- * display the latency histogram
- */
-static int cachefiles_histogram_show(struct seq_file *m, void *v)
-{
- unsigned long index;
- unsigned x, y, z, t;
-
- switch ((unsigned long) v) {
- case 1:
- seq_puts(m, "JIFS SECS LOOKUPS MKDIRS CREATES\n");
- return 0;
- case 2:
- seq_puts(m, "===== ===== ========= ========= =========\n");
- return 0;
- default:
- index = (unsigned long) v - 3;
- x = atomic_read(&cachefiles_lookup_histogram[index]);
- y = atomic_read(&cachefiles_mkdir_histogram[index]);
- z = atomic_read(&cachefiles_create_histogram[index]);
- if (x == 0 && y == 0 && z == 0)
- return 0;
-
- t = (index * 1000) / HZ;
-
- seq_printf(m, "%4lu 0.%03u %9u %9u %9u\n", index, t, x, y, z);
- return 0;
- }
-}
-
-/*
- * set up the iterator to start reading from the first line
- */
-static void *cachefiles_histogram_start(struct seq_file *m, loff_t *_pos)
-{
- if ((unsigned long long)*_pos >= HZ + 2)
- return NULL;
- if (*_pos == 0)
- *_pos = 1;
- return (void *)(unsigned long) *_pos;
-}
-
-/*
- * move to the next line
- */
-static void *cachefiles_histogram_next(struct seq_file *m, void *v, loff_t *pos)
-{
- (*pos)++;
- return (unsigned long long)*pos > HZ + 2 ?
- NULL : (void *)(unsigned long) *pos;
-}
-
-/*
- * clean up after reading
- */
-static void cachefiles_histogram_stop(struct seq_file *m, void *v)
-{
-}
-
-static const struct seq_operations cachefiles_histogram_ops = {
- .start = cachefiles_histogram_start,
- .stop = cachefiles_histogram_stop,
- .next = cachefiles_histogram_next,
- .show = cachefiles_histogram_show,
-};
-
-/*
- * open "/proc/fs/cachefiles/XXX" which provide statistics summaries
- */
-static int cachefiles_histogram_open(struct inode *inode, struct file *file)
-{
- return seq_open(file, &cachefiles_histogram_ops);
-}
-
-static const struct file_operations cachefiles_histogram_fops = {
- .owner = THIS_MODULE,
- .open = cachefiles_histogram_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-
-/*
- * initialise the /proc/fs/cachefiles/ directory
- */
-int __init cachefiles_proc_init(void)
-{
- _enter("");
-
- if (!proc_mkdir("fs/cachefiles", NULL))
- goto error_dir;
-
- if (!proc_create("fs/cachefiles/histogram", S_IFREG | 0444, NULL,
- &cachefiles_histogram_fops))
- goto error_histogram;
-
- _leave(" = 0");
- return 0;
-
-error_histogram:
- remove_proc_entry("fs/cachefiles", NULL);
-error_dir:
- _leave(" = -ENOMEM");
- return -ENOMEM;
-}
-
-/*
- * clean up the /proc/fs/cachefiles/ directory
- */
-void cachefiles_proc_cleanup(void)
-{
- remove_proc_entry("fs/cachefiles/histogram", NULL);
- remove_proc_entry("fs/cachefiles", NULL);
-}
diff --git a/ANDROID_3.4.5/fs/cachefiles/rdwr.c b/ANDROID_3.4.5/fs/cachefiles/rdwr.c
deleted file mode 100644
index 0e3c0924..00000000
--- a/ANDROID_3.4.5/fs/cachefiles/rdwr.c
+++ /dev/null
@@ -1,984 +0,0 @@
-/* Storage object read/write
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#include <linux/mount.h>
-#include <linux/slab.h>
-#include <linux/file.h>
-#include "internal.h"
-
-/*
- * detect wake up events generated by the unlocking of pages in which we're
- * interested
- * - we use this to detect read completion of backing pages
- * - the caller holds the waitqueue lock
- */
-static int cachefiles_read_waiter(wait_queue_t *wait, unsigned mode,
- int sync, void *_key)
-{
- struct cachefiles_one_read *monitor =
- container_of(wait, struct cachefiles_one_read, monitor);
- struct cachefiles_object *object;
- struct wait_bit_key *key = _key;
- struct page *page = wait->private;
-
- ASSERT(key);
-
- _enter("{%lu},%u,%d,{%p,%u}",
- monitor->netfs_page->index, mode, sync,
- key->flags, key->bit_nr);
-
- if (key->flags != &page->flags ||
- key->bit_nr != PG_locked)
- return 0;
-
- _debug("--- monitor %p %lx ---", page, page->flags);
-
- if (!PageUptodate(page) && !PageError(page)) {
- /* unlocked, not uptodate and not erronous? */
- _debug("page probably truncated");
- }
-
- /* remove from the waitqueue */
- list_del(&wait->task_list);
-
- /* move onto the action list and queue for FS-Cache thread pool */
- ASSERT(monitor->op);
-
- object = container_of(monitor->op->op.object,
- struct cachefiles_object, fscache);
-
- spin_lock(&object->work_lock);
- list_add_tail(&monitor->op_link, &monitor->op->to_do);
- spin_unlock(&object->work_lock);
-
- fscache_enqueue_retrieval(monitor->op);
- return 0;
-}
-
-/*
- * handle a probably truncated page
- * - check to see if the page is still relevant and reissue the read if
- * possible
- * - return -EIO on error, -ENODATA if the page is gone, -EINPROGRESS if we
- * must wait again and 0 if successful
- */
-static int cachefiles_read_reissue(struct cachefiles_object *object,
- struct cachefiles_one_read *monitor)
-{
- struct address_space *bmapping = object->backer->d_inode->i_mapping;
- struct page *backpage = monitor->back_page, *backpage2;
- int ret;
-
- kenter("{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]");
- return -ENODATA;
- }
-
- backpage2 = find_get_page(bmapping, backpage->index);
- if (!backpage2) {
- kleave(" = -ENODATA [gone]");
- return -ENODATA;
- }
-
- if (backpage != backpage2) {
- put_page(backpage2);
- kleave(" = -ENODATA [different]");
- return -ENODATA;
- }
-
- /* the page is still there and we already have a ref on it, so we don't
- * need a second */
- put_page(backpage2);
-
- INIT_LIST_HEAD(&monitor->op_link);
- add_page_wait_queue(backpage, &monitor->monitor);
-
- if (trylock_page(backpage)) {
- ret = -EIO;
- if (PageError(backpage))
- goto unlock_discard;
- ret = 0;
- if (PageUptodate(backpage))
- goto unlock_discard;
-
- kdebug("reissue read");
- ret = bmapping->a_ops->readpage(NULL, backpage);
- if (ret < 0)
- goto unlock_discard;
- }
-
- /* but the page may have been read before the monitor was installed, so
- * the monitor may miss the event - so we have to ensure that we do get
- * one in such a case */
- if (trylock_page(backpage)) {
- _debug("jumpstart %p {%lx}", backpage, backpage->flags);
- unlock_page(backpage);
- }
-
- /* it'll reappear on the todo list */
- kleave(" = -EINPROGRESS");
- return -EINPROGRESS;
-
-unlock_discard:
- unlock_page(backpage);
- spin_lock_irq(&object->work_lock);
- list_del(&monitor->op_link);
- spin_unlock_irq(&object->work_lock);
- kleave(" = %d", ret);
- return ret;
-}
-
-/*
- * copy data from backing pages to netfs pages to complete a read operation
- * - driven by FS-Cache's thread pool
- */
-static void cachefiles_read_copier(struct fscache_operation *_op)
-{
- struct cachefiles_one_read *monitor;
- struct cachefiles_object *object;
- struct fscache_retrieval *op;
- struct pagevec pagevec;
- int error, max;
-
- op = container_of(_op, struct fscache_retrieval, op);
- object = container_of(op->op.object,
- struct cachefiles_object, fscache);
-
- _enter("{ino=%lu}", object->backer->d_inode->i_ino);
-
- pagevec_init(&pagevec, 0);
-
- max = 8;
- spin_lock_irq(&object->work_lock);
-
- while (!list_empty(&op->to_do)) {
- monitor = list_entry(op->to_do.next,
- struct cachefiles_one_read, op_link);
- list_del(&monitor->op_link);
-
- spin_unlock_irq(&object->work_lock);
-
- _debug("- copy {%lu}", monitor->back_page->index);
-
- recheck:
- 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);
- error = 0;
- } else if (!PageError(monitor->back_page)) {
- /* the page has probably been truncated */
- error = cachefiles_read_reissue(object, monitor);
- if (error == -EINPROGRESS)
- goto next;
- goto recheck;
- } else {
- cachefiles_io_error_obj(
- object,
- "Readpage failed on backing file %lx",
- (unsigned long) monitor->back_page->flags);
- error = -EIO;
- }
-
- page_cache_release(monitor->back_page);
-
- fscache_end_io(op, monitor->netfs_page, error);
- page_cache_release(monitor->netfs_page);
- fscache_put_retrieval(op);
- kfree(monitor);
-
- next:
- /* let the thread pool have some air occasionally */
- max--;
- if (max < 0 || need_resched()) {
- if (!list_empty(&op->to_do))
- fscache_enqueue_retrieval(op);
- _leave(" [maxed out]");
- return;
- }
-
- spin_lock_irq(&object->work_lock);
- }
-
- spin_unlock_irq(&object->work_lock);
- _leave("");
-}
-
-/*
- * read the corresponding page to the given set from the backing file
- * - an uncertain page is simply discarded, to be tried again another time
- */
-static int cachefiles_read_backing_file_one(struct cachefiles_object *object,
- struct fscache_retrieval *op,
- struct page *netpage,
- struct pagevec *pagevec)
-{
- struct cachefiles_one_read *monitor;
- struct address_space *bmapping;
- struct page *newpage, *backpage;
- int ret;
-
- _enter("");
-
- pagevec_reinit(pagevec);
-
- _debug("read back %p{%lu,%d}",
- netpage, netpage->index, page_count(netpage));
-
- monitor = kzalloc(sizeof(*monitor), GFP_KERNEL);
- if (!monitor)
- goto nomem;
-
- monitor->netfs_page = netpage;
- monitor->op = fscache_get_retrieval(op);
-
- init_waitqueue_func_entry(&monitor->monitor, cachefiles_read_waiter);
-
- /* attempt to get hold of the backing page */
- bmapping = object->backer->d_inode->i_mapping;
- newpage = NULL;
-
- for (;;) {
- backpage = find_get_page(bmapping, netpage->index);
- if (backpage)
- goto backing_page_already_present;
-
- if (!newpage) {
- newpage = page_cache_alloc_cold(bmapping);
- if (!newpage)
- goto nomem_monitor;
- }
-
- ret = add_to_page_cache(newpage, bmapping,
- netpage->index, GFP_KERNEL);
- 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 */
-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)
- goto read_error;
-
- /* set the monitor to transfer the data across */
-monitor_backing_page:
- _debug("- monitor add");
-
- /* install the monitor */
- page_cache_get(monitor->netfs_page);
- page_cache_get(backpage);
- monitor->back_page = backpage;
- monitor->monitor.private = backpage;
- add_page_wait_queue(backpage, &monitor->monitor);
- monitor = NULL;
-
- /* but the page may have been read before the monitor was installed, so
- * the monitor may miss the event - so we have to ensure that we do get
- * one in such a case */
- if (trylock_page(backpage)) {
- _debug("jumpstart %p {%lx}", backpage, backpage->flags);
- unlock_page(backpage);
- }
- goto success;
-
- /* if the backing page is already present, it can be in one of
- * three states: read in progress, read failed or read okay */
-backing_page_already_present:
- _debug("- present");
-
- if (newpage) {
- page_cache_release(newpage);
- newpage = NULL;
- }
-
- if (PageError(backpage))
- goto io_error;
-
- if (PageUptodate(backpage))
- goto backing_page_already_uptodate;
-
- if (!trylock_page(backpage))
- goto monitor_backing_page;
- _debug("read %p {%lx}", backpage, backpage->flags);
- goto read_backing_page;
-
- /* the backing page is already up to date, attach the netfs
- * page to the pagecache and LRU and copy the data across */
-backing_page_already_uptodate:
- _debug("- uptodate");
-
- pagevec_add(pagevec, netpage);
- fscache_mark_pages_cached(op, pagevec);
-
- copy_highpage(netpage, backpage);
- fscache_end_io(op, netpage, 0);
-
-success:
- _debug("success");
- ret = 0;
-
-out:
- if (backpage)
- page_cache_release(backpage);
- if (monitor) {
- fscache_put_retrieval(monitor->op);
- kfree(monitor);
- }
- _leave(" = %d", ret);
- return ret;
-
-read_error:
- _debug("read error %d", ret);
- if (ret == -ENOMEM)
- goto out;
-io_error:
- cachefiles_io_error_obj(object, "Page read error on backing file");
- ret = -ENOBUFS;
- goto out;
-
-nomem_page:
- page_cache_release(newpage);
-nomem_monitor:
- fscache_put_retrieval(monitor->op);
- kfree(monitor);
-nomem:
- _leave(" = -ENOMEM");
- return -ENOMEM;
-}
-
-/*
- * read a page from the cache or allocate a block in which to store it
- * - cache withdrawal is prevented by the caller
- * - returns -EINTR if interrupted
- * - returns -ENOMEM if ran out of memory
- * - returns -ENOBUFS if no buffers can be made available
- * - returns -ENOBUFS if page is beyond EOF
- * - if the page is backed by a block in the cache:
- * - a read will be started which will call the callback on completion
- * - 0 will be returned
- * - else if the page is unbacked:
- * - the metadata will be retained
- * - -ENODATA will be returned
- */
-int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
- struct page *page,
- gfp_t gfp)
-{
- struct cachefiles_object *object;
- struct cachefiles_cache *cache;
- struct pagevec pagevec;
- struct inode *inode;
- sector_t block0, block;
- unsigned shift;
- int ret;
-
- object = container_of(op->op.object,
- struct cachefiles_object, fscache);
- cache = container_of(object->fscache.cache,
- struct cachefiles_cache, cache);
-
- _enter("{%p},{%lx},,,", object, page->index);
-
- if (!object->backer)
- return -ENOBUFS;
-
- inode = object->backer->d_inode;
- ASSERT(S_ISREG(inode->i_mode));
- ASSERT(inode->i_mapping->a_ops->bmap);
- ASSERT(inode->i_mapping->a_ops->readpages);
-
- /* calculate the shift required to use bmap */
- if (inode->i_sb->s_blocksize > PAGE_SIZE)
- return -ENOBUFS;
-
- shift = PAGE_SHIFT - inode->i_sb->s_blocksize_bits;
-
- op->op.flags &= FSCACHE_OP_KEEP_FLAGS;
- op->op.flags |= FSCACHE_OP_ASYNC;
- op->op.processor = cachefiles_read_copier;
-
- pagevec_init(&pagevec, 0);
-
- /* we assume the absence or presence of the first block is a good
- * enough indication for the page as a whole
- * - TODO: don't use bmap() for this as it is _not_ actually good
- * enough for this as it doesn't indicate errors, but it's all we've
- * got for the moment
- */
- block0 = page->index;
- block0 <<= shift;
-
- block = inode->i_mapping->a_ops->bmap(inode->i_mapping, block0);
- _debug("%llx -> %llx",
- (unsigned long long) block0,
- (unsigned long long) block);
-
- 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);
- } 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);
- ret = -ENODATA;
- } else {
- ret = -ENOBUFS;
- }
-
- _leave(" = %d", ret);
- return ret;
-}
-
-/*
- * read the corresponding pages to the given set from the backing file
- * - any uncertain pages are simply discarded, to be tried again another time
- */
-static int cachefiles_read_backing_file(struct cachefiles_object *object,
- struct fscache_retrieval *op,
- struct list_head *list,
- struct pagevec *mark_pvec)
-{
- 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);
-
- _debug("read back %p{%lu,%d}",
- netpage, netpage->index, page_count(netpage));
-
- if (!monitor) {
- monitor = kzalloc(sizeof(*monitor), GFP_KERNEL);
- if (!monitor)
- goto nomem;
-
- monitor->op = fscache_get_retrieval(op);
- init_waitqueue_func_entry(&monitor->monitor,
- cachefiles_read_waiter);
- }
-
- for (;;) {
- backpage = find_get_page(bmapping, netpage->index);
- if (backpage)
- goto backing_page_already_present;
-
- if (!newpage) {
- newpage = page_cache_alloc_cold(bmapping);
- if (!newpage)
- goto nomem;
- }
-
- ret = add_to_page_cache(newpage, bmapping,
- netpage->index, GFP_KERNEL);
- 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 */
- 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)
- goto read_error;
-
- /* add the netfs page to the pagecache and LRU, and set the
- * monitor to transfer the data across */
- monitor_backing_page:
- _debug("- monitor add");
-
- ret = add_to_page_cache(netpage, op->mapping, netpage->index,
- GFP_KERNEL);
- if (ret < 0) {
- if (ret == -EEXIST) {
- page_cache_release(netpage);
- 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;
-
- page_cache_get(backpage);
- monitor->back_page = backpage;
- monitor->monitor.private = backpage;
- add_page_wait_queue(backpage, &monitor->monitor);
- monitor = NULL;
-
- /* but the page may have been read before the monitor was
- * installed, so the monitor may miss the event - so we have to
- * ensure that we do get one in such a case */
- if (trylock_page(backpage)) {
- _debug("2unlock %p {%lx}", backpage, backpage->flags);
- unlock_page(backpage);
- }
-
- page_cache_release(backpage);
- backpage = NULL;
-
- page_cache_release(netpage);
- netpage = NULL;
- continue;
-
- /* if the backing page is already present, it can be in one of
- * three states: read in progress, read failed or read okay */
- backing_page_already_present:
- _debug("- present %p", backpage);
-
- if (PageError(backpage))
- goto io_error;
-
- if (PageUptodate(backpage))
- goto backing_page_already_uptodate;
-
- _debug("- not ready %p{%lx}", backpage, backpage->flags);
-
- if (!trylock_page(backpage))
- goto monitor_backing_page;
-
- if (PageError(backpage)) {
- _debug("error %lx", backpage->flags);
- unlock_page(backpage);
- goto io_error;
- }
-
- if (PageUptodate(backpage))
- goto backing_page_already_uptodate_unlock;
-
- /* we've locked a page that's neither up to date nor erroneous,
- * so we need to attempt to read it again */
- goto reread_backing_page;
-
- /* the backing page is already up to date, attach the netfs
- * page to the pagecache and LRU and copy the data across */
- backing_page_already_uptodate_unlock:
- _debug("uptodate %lx", backpage->flags);
- unlock_page(backpage);
- backing_page_already_uptodate:
- _debug("- uptodate");
-
- ret = add_to_page_cache(netpage, op->mapping, netpage->index,
- GFP_KERNEL);
- if (ret < 0) {
- if (ret == -EEXIST) {
- page_cache_release(netpage);
- continue;
- }
- goto nomem;
- }
-
- copy_highpage(netpage, backpage);
-
- 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_end_io(op, netpage, 0);
- page_cache_release(netpage);
- netpage = NULL;
- continue;
- }
-
- netpage = NULL;
-
- _debug("out");
-
-out:
- /* tidy up */
- pagevec_lru_add_file(&lru_pvec);
-
- if (newpage)
- page_cache_release(newpage);
- if (netpage)
- page_cache_release(netpage);
- if (backpage)
- page_cache_release(backpage);
- if (monitor) {
- fscache_put_retrieval(op);
- kfree(monitor);
- }
-
- list_for_each_entry_safe(netpage, _n, list, lru) {
- list_del(&netpage->lru);
- page_cache_release(netpage);
- }
-
- _leave(" = %d", ret);
- return ret;
-
-nomem:
- _debug("nomem");
- ret = -ENOMEM;
- goto out;
-
-read_error:
- _debug("read error %d", ret);
- if (ret == -ENOMEM)
- goto out;
-io_error:
- cachefiles_io_error_obj(object, "Page read error on backing file");
- ret = -ENOBUFS;
- goto out;
-}
-
-/*
- * read a list of pages from the cache or allocate blocks in which to store
- * them
- */
-int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
- struct list_head *pages,
- unsigned *nr_pages,
- gfp_t gfp)
-{
- struct cachefiles_object *object;
- struct cachefiles_cache *cache;
- struct list_head backpages;
- struct pagevec pagevec;
- struct inode *inode;
- struct page *page, *_n;
- unsigned shift, nrbackpages;
- int ret, ret2, space;
-
- object = container_of(op->op.object,
- struct cachefiles_object, fscache);
- cache = container_of(object->fscache.cache,
- struct cachefiles_cache, cache);
-
- _enter("{OBJ%x,%d},,%d,,",
- object->fscache.debug_id, atomic_read(&op->op.usage),
- *nr_pages);
-
- if (!object->backer)
- return -ENOBUFS;
-
- space = 1;
- if (cachefiles_has_space(cache, 0, *nr_pages) < 0)
- space = 0;
-
- inode = object->backer->d_inode;
- ASSERT(S_ISREG(inode->i_mode));
- ASSERT(inode->i_mapping->a_ops->bmap);
- ASSERT(inode->i_mapping->a_ops->readpages);
-
- /* calculate the shift required to use bmap */
- if (inode->i_sb->s_blocksize > PAGE_SIZE)
- return -ENOBUFS;
-
- shift = PAGE_SHIFT - inode->i_sb->s_blocksize_bits;
-
- pagevec_init(&pagevec, 0);
-
- op->op.flags &= FSCACHE_OP_KEEP_FLAGS;
- op->op.flags |= FSCACHE_OP_ASYNC;
- op->op.processor = cachefiles_read_copier;
-
- INIT_LIST_HEAD(&backpages);
- nrbackpages = 0;
-
- ret = space ? -ENODATA : -ENOBUFS;
- list_for_each_entry_safe(page, _n, pages, lru) {
- sector_t block0, block;
-
- /* we assume the absence or presence of the first block is a
- * good enough indication for the page as a whole
- * - TODO: don't use bmap() for this as it is _not_ actually
- * good enough for this as it doesn't indicate errors, but
- * it's all we've got for the moment
- */
- block0 = page->index;
- block0 <<= shift;
-
- block = inode->i_mapping->a_ops->bmap(inode->i_mapping,
- block0);
- _debug("%llx -> %llx",
- (unsigned long long) block0,
- (unsigned long long) block);
-
- if (block) {
- /* we have data - add it to the list to give to the
- * backing fs */
- list_move(&page->lru, &backpages);
- (*nr_pages)--;
- nrbackpages++;
- } else if (space && pagevec_add(&pagevec, page) == 0) {
- fscache_mark_pages_cached(op, &pagevec);
- ret = -ENODATA;
- }
- }
-
- if (pagevec_count(&pagevec) > 0)
- fscache_mark_pages_cached(op, &pagevec);
-
- if (list_empty(pages))
- ret = 0;
-
- /* 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);
- 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;
-}
-
-/*
- * allocate a block in the cache in which to store a page
- * - cache withdrawal is prevented by the caller
- * - returns -EINTR if interrupted
- * - returns -ENOMEM if ran out of memory
- * - returns -ENOBUFS if no buffers can be made available
- * - returns -ENOBUFS if page is beyond EOF
- * - otherwise:
- * - the metadata will be retained
- * - 0 will be returned
- */
-int cachefiles_allocate_page(struct fscache_retrieval *op,
- struct page *page,
- gfp_t gfp)
-{
- struct cachefiles_object *object;
- struct cachefiles_cache *cache;
- struct pagevec pagevec;
- int ret;
-
- object = container_of(op->op.object,
- struct cachefiles_object, fscache);
- cache = container_of(object->fscache.cache,
- struct cachefiles_cache, cache);
-
- _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 {
- ret = -ENOBUFS;
- }
-
- _leave(" = %d", ret);
- return ret;
-}
-
-/*
- * allocate blocks in the cache in which to store a set of pages
- * - cache withdrawal is prevented by the caller
- * - returns -EINTR if interrupted
- * - returns -ENOMEM if ran out of memory
- * - returns -ENOBUFS if some buffers couldn't be made available
- * - returns -ENOBUFS if some pages are beyond EOF
- * - otherwise:
- * - -ENODATA will be returned
- * - metadata will be retained for any page marked
- */
-int cachefiles_allocate_pages(struct fscache_retrieval *op,
- struct list_head *pages,
- unsigned *nr_pages,
- gfp_t gfp)
-{
- struct cachefiles_object *object;
- struct cachefiles_cache *cache;
- struct pagevec pagevec;
- struct page *page;
- int ret;
-
- object = container_of(op->op.object,
- struct cachefiles_object, fscache);
- cache = container_of(object->fscache.cache,
- struct cachefiles_cache, cache);
-
- _enter("%p,,,%d,", object, *nr_pages);
-
- ret = cachefiles_has_space(cache, 0, *nr_pages);
- if (ret == 0) {
- pagevec_init(&pagevec, 0);
-
- list_for_each_entry(page, pages, lru) {
- if (pagevec_add(&pagevec, page) == 0)
- fscache_mark_pages_cached(op, &pagevec);
- }
-
- if (pagevec_count(&pagevec) > 0)
- fscache_mark_pages_cached(op, &pagevec);
- ret = -ENODATA;
- } else {
- ret = -ENOBUFS;
- }
-
- _leave(" = %d", ret);
- return ret;
-}
-
-/*
- * request a page be stored in the cache
- * - cache withdrawal is prevented by the caller
- * - this request may be ignored if there's no cache block available, in which
- * case -ENOBUFS will be returned
- * - if the op is in progress, 0 will be returned
- */
-int cachefiles_write_page(struct fscache_storage *op, struct page *page)
-{
- struct cachefiles_object *object;
- struct cachefiles_cache *cache;
- mm_segment_t old_fs;
- struct file *file;
- loff_t pos, eof;
- size_t len;
- void *data;
- int ret;
-
- ASSERT(op != NULL);
- ASSERT(page != NULL);
-
- object = container_of(op->op.object,
- struct cachefiles_object, fscache);
-
- _enter("%p,%p{%lx},,,", object, page, page->index);
-
- if (!object->backer) {
- _leave(" = -ENOBUFS");
- return -ENOBUFS;
- }
-
- ASSERT(S_ISREG(object->backer->d_inode->i_mode));
-
- cache = container_of(object->fscache.cache,
- struct cachefiles_cache, cache);
-
- /* 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);
- if (IS_ERR(file)) {
- ret = PTR_ERR(file);
- } else {
- ret = -EIO;
- if (file->f_op->write) {
- pos = (loff_t) page->index << PAGE_SHIFT;
-
- /* we mustn't write more data than we have, so we have
- * to beware of a partial page at EOF */
- eof = object->fscache.store_limit_l;
- len = PAGE_SIZE;
- if (eof & ~PAGE_MASK) {
- ASSERTCMP(pos, <, eof);
- if (eof - pos < PAGE_SIZE) {
- _debug("cut short %llx to %llx",
- pos, eof);
- len = eof - pos;
- ASSERTCMP(pos + len, ==, eof);
- }
- }
-
- data = kmap(page);
- 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);
- if (ret != len)
- ret = -EIO;
- }
- fput(file);
- }
-
- if (ret < 0) {
- if (ret == -EIO)
- cachefiles_io_error_obj(
- object, "Write page to backing file failed");
- ret = -ENOBUFS;
- }
-
- _leave(" = %d", ret);
- return ret;
-}
-
-/*
- * detach a backing block from a page
- * - cache withdrawal is prevented by the caller
- */
-void cachefiles_uncache_page(struct fscache_object *_object, struct page *page)
-{
- struct cachefiles_object *object;
- struct cachefiles_cache *cache;
-
- object = container_of(_object, struct cachefiles_object, fscache);
- cache = container_of(object->fscache.cache,
- struct cachefiles_cache, cache);
-
- _enter("%p,{%lu}", object, page->index);
-
- spin_unlock(&object->fscache.cookie->lock);
-}
diff --git a/ANDROID_3.4.5/fs/cachefiles/security.c b/ANDROID_3.4.5/fs/cachefiles/security.c
deleted file mode 100644
index 039b5011..00000000
--- a/ANDROID_3.4.5/fs/cachefiles/security.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/* CacheFiles security management
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#include <linux/fs.h>
-#include <linux/cred.h>
-#include "internal.h"
-
-/*
- * determine the security context within which we access the cache from within
- * the kernel
- */
-int cachefiles_get_security_ID(struct cachefiles_cache *cache)
-{
- struct cred *new;
- int ret;
-
- _enter("{%s}", cache->secctx);
-
- new = prepare_kernel_cred(current);
- if (!new) {
- ret = -ENOMEM;
- goto error;
- }
-
- if (cache->secctx) {
- 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",
- ret);
- goto error;
- }
- }
-
- cache->cache_cred = new;
- ret = 0;
-error:
- _leave(" = %d", ret);
- return ret;
-}
-
-/*
- * see if mkdir and create can be performed in the root directory
- */
-static int cachefiles_check_cache_dir(struct cachefiles_cache *cache,
- struct dentry *root)
-{
- int ret;
-
- ret = security_inode_mkdir(root->d_inode, root, 0);
- if (ret < 0) {
- printk(KERN_ERR "CacheFiles:"
- " 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",
- ret);
-
- return ret;
-}
-
-/*
- * check the security details of the on-disk cache
- * - must be called with security override in force
- * - must return with a security override in force - even in the case of an
- * error
- */
-int cachefiles_determine_cache_security(struct cachefiles_cache *cache,
- struct dentry *root,
- const struct cred **_saved_cred)
-{
- struct cred *new;
- int ret;
-
- _enter("");
-
- /* duplicate the cache creds for COW (the override is currently in
- * force, so we can use prepare_creds() to do this) */
- new = prepare_creds();
- if (!new)
- return -ENOMEM;
-
- cachefiles_end_secure(cache, *_saved_cred);
-
- /* use the cache root dir's security context as the basis with
- * which create files */
- ret = set_create_files_as(new, root->d_inode);
- if (ret < 0) {
- abort_creds(new);
- cachefiles_begin_secure(cache, _saved_cred);
- _leave(" = %d [cfa]", ret);
- return ret;
- }
-
- put_cred(cache->cache_cred);
- cache->cache_cred = new;
-
- cachefiles_begin_secure(cache, _saved_cred);
- ret = cachefiles_check_cache_dir(cache, root);
-
- if (ret == -EOPNOTSUPP)
- ret = 0;
- _leave(" = %d", ret);
- return ret;
-}
diff --git a/ANDROID_3.4.5/fs/cachefiles/xattr.c b/ANDROID_3.4.5/fs/cachefiles/xattr.c
deleted file mode 100644
index e18b183b..00000000
--- a/ANDROID_3.4.5/fs/cachefiles/xattr.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/* CacheFiles extended attribute management
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/fsnotify.h>
-#include <linux/quotaops.h>
-#include <linux/xattr.h>
-#include <linux/slab.h>
-#include "internal.h"
-
-static const char cachefiles_xattr_cache[] =
- XATTR_USER_PREFIX "CacheFiles.cache";
-
-/*
- * check the type label on an object
- * - done using xattrs
- */
-int cachefiles_check_object_type(struct cachefiles_object *object)
-{
- struct dentry *dentry = object->dentry;
- char type[3], xtype[3];
- int ret;
-
- ASSERT(dentry);
- ASSERT(dentry->d_inode);
-
- if (!object->fscache.cookie)
- strcpy(type, "C3");
- else
- snprintf(type, 3, "%02x", object->fscache.cookie->def->type);
-
- _enter("%p{%s}", object, type);
-
- /* attempt to install a type label directly */
- ret = vfs_setxattr(dentry, cachefiles_xattr_cache, type, 2,
- XATTR_CREATE);
- if (ret == 0) {
- _debug("SET"); /* we succeeded */
- goto error;
- }
-
- if (ret != -EEXIST) {
- kerror("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);
- goto error;
- }
-
- /* read the current type label */
- ret = vfs_getxattr(dentry, cachefiles_xattr_cache, xtype, 3);
- if (ret < 0) {
- if (ret == -ERANGE)
- goto bad_type_length;
-
- kerror("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);
- goto error;
- }
-
- /* check the type is what we're expecting */
- if (ret != 2)
- goto bad_type_length;
-
- if (xtype[0] != type[0] || xtype[1] != type[1])
- goto bad_type;
-
- ret = 0;
-
-error:
- _leave(" = %d", ret);
- return ret;
-
-bad_type_length:
- kerror("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",
- dentry->d_name.len, dentry->d_name.len,
- dentry->d_name.name, dentry->d_inode->i_ino,
- xtype, type);
- ret = -EIO;
- goto error;
-}
-
-/*
- * set the state xattr on a cache file
- */
-int cachefiles_set_object_xattr(struct cachefiles_object *object,
- struct cachefiles_xattr *auxdata)
-{
- 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);
-
- ret = vfs_setxattr(dentry, cachefiles_xattr_cache,
- &auxdata->type, auxdata->len,
- XATTR_CREATE);
- if (ret < 0 && ret != -ENOMEM)
- cachefiles_io_error_obj(
- object,
- "Failed to set xattr with error %d", ret);
-
- _leave(" = %d", ret);
- return ret;
-}
-
-/*
- * update the state xattr on a cache file
- */
-int cachefiles_update_object_xattr(struct cachefiles_object *object,
- struct cachefiles_xattr *auxdata)
-{
- 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);
-
- ret = vfs_setxattr(dentry, cachefiles_xattr_cache,
- &auxdata->type, auxdata->len,
- XATTR_REPLACE);
- if (ret < 0 && ret != -ENOMEM)
- cachefiles_io_error_obj(
- object,
- "Failed to update xattr with error %d", ret);
-
- _leave(" = %d", ret);
- return ret;
-}
-
-/*
- * check the state xattr on a cache file
- * - return -ESTALE if the object should be deleted
- */
-int cachefiles_check_object_xattr(struct cachefiles_object *object,
- struct cachefiles_xattr *auxdata)
-{
- struct cachefiles_xattr *auxbuf;
- struct dentry *dentry = object->dentry;
- int ret;
-
- _enter("%p,#%d", object, auxdata->len);
-
- ASSERT(dentry);
- ASSERT(dentry->d_inode);
-
- auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, GFP_KERNEL);
- if (!auxbuf) {
- _leave(" = -ENOMEM");
- return -ENOMEM;
- }
-
- /* read the current type label */
- ret = vfs_getxattr(dentry, cachefiles_xattr_cache,
- &auxbuf->type, 512 + 1);
- if (ret < 0) {
- if (ret == -ENODATA)
- goto stale; /* no attribute - power went off
- * mid-cull? */
-
- if (ret == -ERANGE)
- goto bad_type_length;
-
- cachefiles_io_error_obj(object,
- "Can't read xattr on %lu (err %d)",
- dentry->d_inode->i_ino, -ret);
- goto error;
- }
-
- /* check the on-disk object */
- if (ret < 1)
- goto bad_type_length;
-
- if (auxbuf->type != auxdata->type)
- goto stale;
-
- auxbuf->len = ret;
-
- /* consult the netfs */
- if (object->fscache.cookie->def->check_aux) {
- enum fscache_checkaux result;
- unsigned int dlen;
-
- dlen = auxbuf->len - 1;
-
- _debug("checkaux %s #%u",
- object->fscache.cookie->def->name, dlen);
-
- result = fscache_check_aux(&object->fscache,
- &auxbuf->data, dlen);
-
- switch (result) {
- /* entry okay as is */
- case FSCACHE_CHECKAUX_OKAY:
- goto okay;
-
- /* entry requires update */
- case FSCACHE_CHECKAUX_NEEDS_UPDATE:
- break;
-
- /* entry requires deletion */
- case FSCACHE_CHECKAUX_OBSOLETE:
- goto stale;
-
- default:
- BUG();
- }
-
- /* update the current label */
- ret = vfs_setxattr(dentry, cachefiles_xattr_cache,
- &auxdata->type, auxdata->len,
- XATTR_REPLACE);
- if (ret < 0) {
- cachefiles_io_error_obj(object,
- "Can't update xattr on %lu"
- " (error %d)",
- dentry->d_inode->i_ino, -ret);
- goto error;
- }
- }
-
-okay:
- ret = 0;
-
-error:
- kfree(auxbuf);
- _leave(" = %d", ret);
- return ret;
-
-bad_type_length:
- kerror("Cache object %lu xattr length incorrect",
- dentry->d_inode->i_ino);
- ret = -EIO;
- goto error;
-
-stale:
- ret = -ESTALE;
- goto error;
-}
-
-/*
- * remove the object's xattr to mark it stale
- */
-int cachefiles_remove_object_xattr(struct cachefiles_cache *cache,
- struct dentry *dentry)
-{
- int ret;
-
- ret = vfs_removexattr(dentry, cachefiles_xattr_cache);
- if (ret < 0) {
- if (ret == -ENOENT || ret == -ENODATA)
- ret = 0;
- else if (ret != -ENOMEM)
- cachefiles_io_error(cache,
- "Can't remove xattr from %lu"
- " (error %d)",
- dentry->d_inode->i_ino, -ret);
- }
-
- _leave(" = %d", ret);
- return ret;
-}