summaryrefslogtreecommitdiff
path: root/fs/cachefiles
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cachefiles')
-rw-r--r--fs/cachefiles/daemon.c2
-rw-r--r--fs/cachefiles/interface.c11
-rw-r--r--fs/cachefiles/internal.h1
-rw-r--r--fs/cachefiles/io.c28
-rw-r--r--fs/cachefiles/key.c3
-rw-r--r--fs/cachefiles/namei.c218
-rw-r--r--fs/cachefiles/ondemand.c14
-rw-r--r--fs/cachefiles/volume.c11
-rw-r--r--fs/cachefiles/xattr.c2
9 files changed, 132 insertions, 158 deletions
diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c
index 1806bff8e59b..4117b145ac94 100644
--- a/fs/cachefiles/daemon.c
+++ b/fs/cachefiles/daemon.c
@@ -102,7 +102,7 @@ static int cachefiles_daemon_open(struct inode *inode, struct file *file)
return -EBUSY;
/* allocate a cache record */
- cache = kzalloc(sizeof(struct cachefiles_cache), GFP_KERNEL);
+ cache = kzalloc_obj(struct cachefiles_cache);
if (!cache) {
cachefiles_open = 0;
return -ENOMEM;
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c
index 3e63cfe15874..a08250d244ea 100644
--- a/fs/cachefiles/interface.c
+++ b/fs/cachefiles/interface.c
@@ -9,6 +9,7 @@
#include <linux/mount.h>
#include <linux/xattr.h>
#include <linux/file.h>
+#include <linux/namei.h>
#include <linux/falloc.h>
#include <trace/events/fscache.h>
#include "internal.h"
@@ -428,11 +429,13 @@ static bool cachefiles_invalidate_cookie(struct fscache_cookie *cookie)
if (!old_tmpfile) {
struct cachefiles_volume *volume = object->volume;
struct dentry *fan = volume->fanout[(u8)cookie->key_hash];
+ struct dentry *obj;
- inode_lock_nested(d_inode(fan), I_MUTEX_PARENT);
- cachefiles_bury_object(volume->cache, object, fan,
- old_file->f_path.dentry,
- FSCACHE_OBJECT_INVALIDATED);
+ obj = start_removing_dentry(fan, old_file->f_path.dentry);
+ if (!IS_ERR(obj))
+ cachefiles_bury_object(volume->cache, object,
+ fan, obj,
+ FSCACHE_OBJECT_INVALIDATED);
}
fput(old_file);
}
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
index 38c236e38cef..b62cd3e9a18e 100644
--- a/fs/cachefiles/internal.h
+++ b/fs/cachefiles/internal.h
@@ -71,7 +71,6 @@ struct cachefiles_object {
int debug_id;
spinlock_t lock;
refcount_t ref;
- u8 d_name_len; /* Length of filename */
enum cachefiles_content content_info:8; /* Info about content presence */
unsigned long flags;
#define CACHEFILES_OBJECT_USING_TMPFILE 0 /* Have an unlinked tmpfile */
diff --git a/fs/cachefiles/io.c b/fs/cachefiles/io.c
index 92058ae43488..d879b80a0bed 100644
--- a/fs/cachefiles/io.c
+++ b/fs/cachefiles/io.c
@@ -63,7 +63,7 @@ static void cachefiles_read_complete(struct kiocb *iocb, long ret)
ret = -ESTALE;
}
- ki->term_func(ki->term_func_priv, ret, ki->was_async);
+ ki->term_func(ki->term_func_priv, ret);
}
cachefiles_put_kiocb(ki);
@@ -93,7 +93,7 @@ static int cachefiles_read(struct netfs_cache_resources *cres,
object = cachefiles_cres_object(cres);
file = cachefiles_cres_file(cres);
- _enter("%pD,%li,%llx,%zx/%llx",
+ _enter("%pD,%llu,%llx,%zx/%llx",
file, file_inode(file)->i_ino, start_pos, len,
i_size_read(file_inode(file)));
@@ -132,7 +132,7 @@ static int cachefiles_read(struct netfs_cache_resources *cres,
}
ret = -ENOMEM;
- ki = kzalloc(sizeof(struct cachefiles_kiocb), GFP_KERNEL);
+ ki = kzalloc_obj(struct cachefiles_kiocb);
if (!ki)
goto presubmission_error;
@@ -188,7 +188,7 @@ in_progress:
presubmission_error:
if (term_func)
- term_func(term_func_priv, ret < 0 ? ret : skipped, false);
+ term_func(term_func_priv, ret < 0 ? ret : skipped);
return ret;
}
@@ -214,7 +214,7 @@ static int cachefiles_query_occupancy(struct netfs_cache_resources *cres,
file = cachefiles_cres_file(cres);
granularity = max_t(size_t, object->volume->cache->bsize, granularity);
- _enter("%pD,%li,%llx,%zx/%llx",
+ _enter("%pD,%llu,%llx,%zx/%llx",
file, file_inode(file)->i_ino, start, len,
i_size_read(file_inode(file)));
@@ -271,7 +271,7 @@ static void cachefiles_write_complete(struct kiocb *iocb, long ret)
atomic_long_sub(ki->b_writing, &object->volume->cache->b_writing);
set_bit(FSCACHE_COOKIE_HAVE_DATA, &object->cookie->flags);
if (ki->term_func)
- ki->term_func(ki->term_func_priv, ret, ki->was_async);
+ ki->term_func(ki->term_func_priv, ret);
cachefiles_put_kiocb(ki);
}
@@ -294,14 +294,14 @@ int __cachefiles_write(struct cachefiles_object *object,
fscache_count_write();
cache = object->volume->cache;
- _enter("%pD,%li,%llx,%zx/%llx",
+ _enter("%pD,%llu,%llx,%zx/%llx",
file, file_inode(file)->i_ino, start_pos, len,
i_size_read(file_inode(file)));
- ki = kzalloc(sizeof(struct cachefiles_kiocb), GFP_KERNEL);
+ ki = kzalloc_obj(struct cachefiles_kiocb);
if (!ki) {
if (term_func)
- term_func(term_func_priv, -ENOMEM, false);
+ term_func(term_func_priv, -ENOMEM);
return -ENOMEM;
}
@@ -347,8 +347,6 @@ int __cachefiles_write(struct cachefiles_object *object,
default:
ki->was_async = false;
cachefiles_write_complete(&ki->iocb, ret);
- if (ret > 0)
- ret = 0;
break;
}
@@ -366,7 +364,7 @@ static int cachefiles_write(struct netfs_cache_resources *cres,
{
if (!fscache_wait_for_operation(cres, FSCACHE_WANT_WRITE)) {
if (term_func)
- term_func(term_func_priv, -ENOBUFS, false);
+ term_func(term_func_priv, -ENOBUFS);
trace_netfs_sreq(term_func_priv, netfs_sreq_trace_cache_nowrite);
return -ENOBUFS;
}
@@ -665,7 +663,7 @@ static void cachefiles_issue_write(struct netfs_io_subrequest *subreq)
pre = CACHEFILES_DIO_BLOCK_SIZE - off;
if (pre >= len) {
fscache_count_dio_misfit();
- netfs_write_subrequest_terminated(subreq, len, false);
+ netfs_write_subrequest_terminated(subreq, len);
return;
}
subreq->transferred += pre;
@@ -691,7 +689,7 @@ static void cachefiles_issue_write(struct netfs_io_subrequest *subreq)
len -= post;
if (len == 0) {
fscache_count_dio_misfit();
- netfs_write_subrequest_terminated(subreq, post, false);
+ netfs_write_subrequest_terminated(subreq, post);
return;
}
iov_iter_truncate(&subreq->io_iter, len);
@@ -703,7 +701,7 @@ static void cachefiles_issue_write(struct netfs_io_subrequest *subreq)
&start, &len, len, true);
cachefiles_end_secure(cache, saved_cred);
if (ret < 0) {
- netfs_write_subrequest_terminated(subreq, ret, false);
+ netfs_write_subrequest_terminated(subreq, ret);
return;
}
diff --git a/fs/cachefiles/key.c b/fs/cachefiles/key.c
index bf935e25bdbe..aae86af48ed5 100644
--- a/fs/cachefiles/key.c
+++ b/fs/cachefiles/key.c
@@ -8,7 +8,7 @@
#include <linux/slab.h>
#include "internal.h"
-static const char cachefiles_charmap[64] =
+static const char cachefiles_charmap[64] __nonstring =
"0123456789" /* 0 - 9 */
"abcdefghijklmnopqrstuvwxyz" /* 10 - 35 */
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* 36 - 61 */
@@ -132,7 +132,6 @@ bool cachefiles_cook_key(struct cachefiles_object *object)
success:
name[len] = 0;
object->d_name = name;
- object->d_name_len = len;
_leave(" = %s", object->d_name);
return true;
}
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index 7cf59713f0f7..2937db690b40 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -93,12 +93,11 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
_enter(",,%s", dirname);
/* search the current directory for the element name */
- inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
retry:
ret = cachefiles_inject_read_error();
if (ret == 0)
- subdir = lookup_one_len(dirname, dir, strlen(dirname));
+ subdir = start_creating(&nop_mnt_idmap, dir, &QSTR(dirname));
else
subdir = ERR_PTR(ret);
trace_cachefiles_lookup(NULL, dir, subdir);
@@ -129,22 +128,28 @@ retry:
if (ret < 0)
goto mkdir_error;
ret = cachefiles_inject_write_error();
- if (ret == 0)
- ret = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), subdir, 0700);
- if (ret < 0) {
+ if (ret == 0) {
+ subdir = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), subdir, 0700, NULL);
+ if (IS_ERR(subdir))
+ ret = PTR_ERR(subdir);
+ } else {
+ end_creating(subdir);
+ subdir = ERR_PTR(ret);
+ }
+ if (IS_ERR(subdir)) {
trace_cachefiles_vfs_error(NULL, d_inode(dir), ret,
cachefiles_trace_mkdir_error);
goto mkdir_error;
}
trace_cachefiles_mkdir(dir, subdir);
- if (unlikely(d_unhashed(subdir))) {
- cachefiles_put_directory(subdir);
+ if (unlikely(d_unhashed(subdir) || d_is_negative(subdir))) {
+ end_creating(subdir);
goto retry;
}
ASSERT(d_backing_inode(subdir));
- _debug("mkdir -> %pd{ino=%lu}",
+ _debug("mkdir -> %pd{ino=%llu}",
subdir, d_backing_inode(subdir)->i_ino);
if (_is_new)
*_is_new = true;
@@ -152,10 +157,10 @@ retry:
/* Tell rmdir() it's not allowed to delete the subdir */
inode_lock(d_inode(subdir));
- inode_unlock(d_inode(dir));
+ end_creating_keep(subdir);
if (!__cachefiles_mark_inode_in_use(NULL, d_inode(subdir))) {
- pr_notice("cachefiles: Inode already in use: %pd (B=%lx)\n",
+ pr_notice("cachefiles: Inode already in use: %pd (B=%llx)\n",
subdir, d_inode(subdir)->i_ino);
goto mark_error;
}
@@ -180,7 +185,7 @@ retry:
!d_backing_inode(subdir)->i_op->unlink)
goto check_error;
- _leave(" = [%lu]", d_backing_inode(subdir)->i_ino);
+ _leave(" = [%llu]", d_backing_inode(subdir)->i_ino);
return subdir;
check_error:
@@ -194,13 +199,11 @@ mark_error:
return ERR_PTR(-EBUSY);
mkdir_error:
- inode_unlock(d_inode(dir));
- dput(subdir);
+ end_creating(subdir);
pr_err("mkdir %s failed with error %d\n", dirname, ret);
return ERR_PTR(ret);
lookup_error:
- inode_unlock(d_inode(dir));
ret = PTR_ERR(subdir);
pr_err("Lookup %s failed with error %d\n", dirname, ret);
return ERR_PTR(ret);
@@ -260,6 +263,8 @@ static int cachefiles_unlink(struct cachefiles_cache *cache,
* - File backed objects are unlinked
* - Directory backed objects are stuffed into the graveyard for userspace to
* delete
+ * On entry dir must be locked. It will be unlocked on exit.
+ * On entry there must be at least 2 refs on rep, one will be dropped on exit.
*/
int cachefiles_bury_object(struct cachefiles_cache *cache,
struct cachefiles_object *object,
@@ -267,7 +272,8 @@ int cachefiles_bury_object(struct cachefiles_cache *cache,
struct dentry *rep,
enum fscache_why_object_killed why)
{
- struct dentry *grave, *trap;
+ struct dentry *grave;
+ struct renamedata rd = {};
struct path path, path_to_graveyard;
char nbuffer[8 + 8 + 1];
int ret;
@@ -275,27 +281,23 @@ int cachefiles_bury_object(struct cachefiles_cache *cache,
_enter(",'%pd','%pd'", dir, rep);
if (rep->d_parent != dir) {
- inode_unlock(d_inode(dir));
+ end_removing(rep);
_leave(" = -ESTALE");
return -ESTALE;
}
/* non-directories can just be unlinked */
if (!d_is_dir(rep)) {
- dget(rep); /* Stop the dentry being negated if it's only pinned
- * by a file struct.
- */
ret = cachefiles_unlink(cache, object, dir, rep, why);
- dput(rep);
+ end_removing(rep);
- inode_unlock(d_inode(dir));
_leave(" = %d", ret);
return ret;
}
/* directories have to be moved to the graveyard */
_debug("move stale object to graveyard");
- inode_unlock(d_inode(dir));
+ end_removing(rep);
try_again:
/* first step is to make up a grave dentry in the graveyard */
@@ -303,77 +305,55 @@ try_again:
(uint32_t) ktime_get_real_seconds(),
(uint32_t) atomic_inc_return(&cache->gravecounter));
- /* do the multiway lock magic */
- trap = lock_rename(cache->graveyard, dir);
- if (IS_ERR(trap))
- return PTR_ERR(trap);
-
- /* do some checks before getting the grave dentry */
- if (rep->d_parent != dir || IS_DEADDIR(d_inode(rep))) {
- /* the entry was probably culled when we dropped the parent dir
- * lock */
- unlock_rename(cache->graveyard, dir);
- _leave(" = 0 [culled?]");
- return 0;
- }
-
- if (!d_can_lookup(cache->graveyard)) {
- unlock_rename(cache->graveyard, dir);
- cachefiles_io_error(cache, "Graveyard no longer a directory");
- return -EIO;
- }
+ rd.mnt_idmap = &nop_mnt_idmap;
+ rd.old_parent = dir;
+ rd.new_parent = cache->graveyard;
+ rd.flags = 0;
+ ret = start_renaming_dentry(&rd, 0, rep, &QSTR(nbuffer));
+ if (ret) {
+ /* Some errors aren't fatal */
+ if (ret == -EXDEV)
+ /* double-lock failed */
+ return ret;
+ if (d_unhashed(rep) || rep->d_parent != dir || IS_DEADDIR(d_inode(rep))) {
+ /* the entry was probably culled when we dropped the parent dir
+ * lock */
+ _leave(" = 0 [culled?]");
+ return 0;
+ }
+ if (ret == -EINVAL || ret == -ENOTEMPTY) {
+ cachefiles_io_error(cache, "May not make directory loop");
+ return -EIO;
+ }
+ if (ret == -ENOMEM) {
+ _leave(" = -ENOMEM");
+ return -ENOMEM;
+ }
- if (trap == rep) {
- unlock_rename(cache->graveyard, dir);
- cachefiles_io_error(cache, "May not make directory loop");
+ cachefiles_io_error(cache, "Lookup error %d", ret);
return -EIO;
}
if (d_mountpoint(rep)) {
- unlock_rename(cache->graveyard, dir);
+ end_renaming(&rd);
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);
- trace_cachefiles_vfs_error(object, d_inode(cache->graveyard),
- PTR_ERR(grave),
- cachefiles_trace_lookup_error);
-
- if (PTR_ERR(grave) == -ENOMEM) {
- _leave(" = -ENOMEM");
- return -ENOMEM;
- }
-
- cachefiles_io_error(cache, "Lookup error %ld", PTR_ERR(grave));
- return -EIO;
- }
-
+ grave = rd.new_dentry;
if (d_is_positive(grave)) {
- unlock_rename(cache->graveyard, dir);
- dput(grave);
+ end_renaming(&rd);
grave = NULL;
cond_resched();
goto try_again;
}
if (d_mountpoint(grave)) {
- unlock_rename(cache->graveyard, dir);
- dput(grave);
+ end_renaming(&rd);
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;
@@ -383,14 +363,6 @@ try_again:
if (ret < 0) {
cachefiles_io_error(cache, "Rename security error %d", ret);
} else {
- struct renamedata rd = {
- .old_mnt_idmap = &nop_mnt_idmap,
- .old_dir = d_inode(dir),
- .old_dentry = rep,
- .new_mnt_idmap = &nop_mnt_idmap,
- .new_dir = d_inode(cache->graveyard),
- .new_dentry = grave,
- };
trace_cachefiles_rename(object, d_inode(rep)->i_ino, why);
ret = cachefiles_inject_read_error();
if (ret == 0)
@@ -404,8 +376,7 @@ try_again:
}
__cachefiles_unmark_inode_in_use(object, d_inode(rep));
- unlock_rename(cache->graveyard, dir);
- dput(grave);
+ end_renaming(&rd);
_leave(" = 0");
return 0;
}
@@ -423,13 +394,12 @@ int cachefiles_delete_object(struct cachefiles_object *object,
_enter(",OBJ%x{%pD}", object->debug_id, object->file);
- /* Stop the dentry being negated if it's only pinned by a file struct. */
- dget(dentry);
-
- inode_lock_nested(d_backing_inode(fan), I_MUTEX_PARENT);
- ret = cachefiles_unlink(volume->cache, object, fan, dentry, why);
- inode_unlock(d_backing_inode(fan));
- dput(dentry);
+ dentry = start_removing_dentry(fan, dentry);
+ if (IS_ERR(dentry))
+ ret = PTR_ERR(dentry);
+ else
+ ret = cachefiles_unlink(volume->cache, object, fan, dentry, why);
+ end_removing(dentry);
return ret;
}
@@ -532,7 +502,7 @@ static bool cachefiles_create_file(struct cachefiles_object *object)
set_bit(FSCACHE_COOKIE_NEEDS_UPDATE, &object->cookie->flags);
set_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags);
- _debug("create -> %pD{ino=%lu}", file, file_inode(file)->i_ino);
+ _debug("create -> %pD{ino=%llu}", file, file_inode(file)->i_ino);
object->file = file;
return true;
}
@@ -552,7 +522,7 @@ static bool cachefiles_open_file(struct cachefiles_object *object,
_enter("%pd", dentry);
if (!cachefiles_mark_inode_in_use(object, d_inode(dentry))) {
- pr_notice("cachefiles: Inode already in use: %pd (B=%lx)\n",
+ pr_notice("cachefiles: Inode already in use: %pd (B=%llx)\n",
dentry, d_inode(dentry)->i_ino);
return false;
}
@@ -627,8 +597,8 @@ bool cachefiles_look_up_object(struct cachefiles_object *object)
/* Look up path "cache/vol/fanout/file". */
ret = cachefiles_inject_read_error();
if (ret == 0)
- dentry = lookup_positive_unlocked(object->d_name, fan,
- object->d_name_len);
+ dentry = lookup_one_positive_unlocked(&nop_mnt_idmap,
+ &QSTR(object->d_name), fan);
else
dentry = ERR_PTR(ret);
trace_cachefiles_lookup(object, fan, dentry);
@@ -642,9 +612,13 @@ bool cachefiles_look_up_object(struct cachefiles_object *object)
if (!d_is_reg(dentry)) {
pr_err("%pd is not a file\n", dentry);
- inode_lock_nested(d_inode(fan), I_MUTEX_PARENT);
- ret = cachefiles_bury_object(volume->cache, object, fan, dentry,
- FSCACHE_OBJECT_IS_WEIRD);
+ struct dentry *de = start_removing_dentry(fan, dentry);
+ if (IS_ERR(de))
+ ret = PTR_ERR(de);
+ else
+ ret = cachefiles_bury_object(volume->cache, object,
+ fan, de,
+ FSCACHE_OBJECT_IS_WEIRD);
dput(dentry);
if (ret < 0)
return false;
@@ -656,7 +630,7 @@ bool cachefiles_look_up_object(struct cachefiles_object *object)
if (!ret)
return false;
- _leave(" = t [%lu]", file_inode(object->file)->i_ino);
+ _leave(" = t [%llu]", file_inode(object->file)->i_ino);
return true;
new_file:
@@ -677,36 +651,41 @@ bool cachefiles_commit_tmpfile(struct cachefiles_cache *cache,
_enter(",%pD", object->file);
- inode_lock_nested(d_inode(fan), I_MUTEX_PARENT);
ret = cachefiles_inject_read_error();
if (ret == 0)
- dentry = lookup_one_len(object->d_name, fan, object->d_name_len);
+ dentry = start_creating(&nop_mnt_idmap, fan, &QSTR(object->d_name));
else
dentry = ERR_PTR(ret);
if (IS_ERR(dentry)) {
trace_cachefiles_vfs_error(object, d_inode(fan), PTR_ERR(dentry),
cachefiles_trace_lookup_error);
_debug("lookup fail %ld", PTR_ERR(dentry));
- goto out_unlock;
+ goto out;
}
- if (!d_is_negative(dentry)) {
+ /*
+ * This loop will only execute more than once if some other thread
+ * races to create the object we are trying to create.
+ */
+ while (!d_is_negative(dentry)) {
ret = cachefiles_unlink(volume->cache, object, fan, dentry,
FSCACHE_OBJECT_IS_STALE);
if (ret < 0)
- goto out_dput;
+ goto out_end;
+
+ end_creating(dentry);
- dput(dentry);
ret = cachefiles_inject_read_error();
if (ret == 0)
- dentry = lookup_one_len(object->d_name, fan, object->d_name_len);
+ dentry = start_creating(&nop_mnt_idmap, fan,
+ &QSTR(object->d_name));
else
dentry = ERR_PTR(ret);
if (IS_ERR(dentry)) {
trace_cachefiles_vfs_error(object, d_inode(fan), PTR_ERR(dentry),
cachefiles_trace_lookup_error);
_debug("lookup fail %ld", PTR_ERR(dentry));
- goto out_unlock;
+ goto out;
}
}
@@ -727,10 +706,9 @@ bool cachefiles_commit_tmpfile(struct cachefiles_cache *cache,
success = true;
}
-out_dput:
- dput(dentry);
-out_unlock:
- inode_unlock(d_inode(fan));
+out_end:
+ end_creating(dentry);
+out:
_leave(" = %u", success);
return success;
}
@@ -746,26 +724,20 @@ static struct dentry *cachefiles_lookup_for_cull(struct cachefiles_cache *cache,
struct dentry *victim;
int ret = -ENOENT;
- inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
+ victim = start_removing(&nop_mnt_idmap, dir, &QSTR(filename));
- victim = lookup_one_len(filename, dir, strlen(filename));
if (IS_ERR(victim))
goto lookup_error;
- if (d_is_negative(victim))
- goto lookup_put;
if (d_inode(victim)->i_flags & S_KERNEL_FILE)
goto lookup_busy;
return victim;
lookup_busy:
ret = -EBUSY;
-lookup_put:
- inode_unlock(d_inode(dir));
- dput(victim);
+ end_removing(victim);
return ERR_PTR(ret);
lookup_error:
- inode_unlock(d_inode(dir));
ret = PTR_ERR(victim);
if (ret == -ENOENT)
return ERR_PTR(-ESTALE); /* Probably got retired by the netfs */
@@ -811,20 +783,24 @@ int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
if (ret < 0)
goto error_unlock;
+ /*
+ * cachefiles_bury_object() expects 2 references to 'victim',
+ * and drops one.
+ */
+ dget(victim);
ret = cachefiles_bury_object(cache, NULL, dir, victim,
FSCACHE_OBJECT_WAS_CULLED);
+ dput(victim);
if (ret < 0)
goto error;
fscache_count_culled();
- dput(victim);
_leave(" = 0");
return 0;
error_unlock:
- inode_unlock(d_inode(dir));
+ end_removing(victim);
error:
- dput(victim);
if (ret == -ENOENT)
return -ESTALE; /* Probably got retired by the netfs */
diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c
index fe3de9ad57bf..0849eaf583cd 100644
--- a/fs/cachefiles/ondemand.c
+++ b/fs/cachefiles/ondemand.c
@@ -83,10 +83,8 @@ static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb,
trace_cachefiles_ondemand_fd_write(object, file_inode(file), pos, len);
ret = __cachefiles_write(object, file, pos, iter, NULL, NULL);
- if (!ret) {
- ret = len;
+ if (ret > 0)
kiocb->ki_pos += ret;
- }
out:
fput(file);
@@ -317,8 +315,9 @@ static int cachefiles_ondemand_get_fd(struct cachefiles_req *req,
goto err_free_id;
}
- anon_file->file = anon_inode_getfile("[cachefiles]",
- &cachefiles_ondemand_fd_fops, object, O_WRONLY);
+ anon_file->file = anon_inode_getfile_fmode("[cachefiles]",
+ &cachefiles_ondemand_fd_fops, object,
+ O_WRONLY, FMODE_PWRITE | FMODE_LSEEK);
if (IS_ERR(anon_file->file)) {
ret = PTR_ERR(anon_file->file);
goto err_put_fd;
@@ -333,8 +332,6 @@ static int cachefiles_ondemand_get_fd(struct cachefiles_req *req,
goto err_put_file;
}
- anon_file->file->f_mode |= FMODE_PWRITE | FMODE_LSEEK;
-
load = (void *)req->msg.data;
load->fd = anon_file->fd;
object->ondemand->ondemand_id = object_id;
@@ -737,8 +734,7 @@ int cachefiles_ondemand_init_obj_info(struct cachefiles_object *object,
if (!cachefiles_in_ondemand_mode(volume->cache))
return 0;
- object->ondemand = kzalloc(sizeof(struct cachefiles_ondemand_info),
- GFP_KERNEL);
+ object->ondemand = kzalloc_obj(struct cachefiles_ondemand_info);
if (!object->ondemand)
return -ENOMEM;
diff --git a/fs/cachefiles/volume.c b/fs/cachefiles/volume.c
index 781aac4ef274..6c0da61362ee 100644
--- a/fs/cachefiles/volume.c
+++ b/fs/cachefiles/volume.c
@@ -7,6 +7,7 @@
#include <linux/fs.h>
#include <linux/slab.h>
+#include <linux/namei.h>
#include "internal.h"
#include <trace/events/fscache.h>
@@ -27,7 +28,7 @@ void cachefiles_acquire_volume(struct fscache_volume *vcookie)
_enter("");
- volume = kzalloc(sizeof(struct cachefiles_volume), GFP_KERNEL);
+ volume = kzalloc_obj(struct cachefiles_volume);
if (!volume)
return;
volume->vcookie = vcookie;
@@ -58,9 +59,11 @@ retry:
if (ret < 0) {
if (ret != -ESTALE)
goto error_dir;
- inode_lock_nested(d_inode(cache->store), I_MUTEX_PARENT);
- cachefiles_bury_object(cache, NULL, cache->store, vdentry,
- FSCACHE_VOLUME_IS_WEIRD);
+ vdentry = start_removing_dentry(cache->store, vdentry);
+ if (!IS_ERR(vdentry))
+ cachefiles_bury_object(cache, NULL, cache->store,
+ vdentry,
+ FSCACHE_VOLUME_IS_WEIRD);
cachefiles_put_directory(volume->dentry);
cond_resched();
goto retry;
diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c
index 52383b1d0ba6..f8ae78b3f7b6 100644
--- a/fs/cachefiles/xattr.c
+++ b/fs/cachefiles/xattr.c
@@ -179,7 +179,7 @@ int cachefiles_remove_object_xattr(struct cachefiles_cache *cache,
ret = 0;
else if (ret != -ENOMEM)
cachefiles_io_error(cache,
- "Can't remove xattr from %lu"
+ "Can't remove xattr from %llu"
" (error %d)",
d_backing_inode(dentry)->i_ino, -ret);
}