diff options
Diffstat (limited to 'fs/cachefiles')
| -rw-r--r-- | fs/cachefiles/daemon.c | 2 | ||||
| -rw-r--r-- | fs/cachefiles/interface.c | 11 | ||||
| -rw-r--r-- | fs/cachefiles/internal.h | 1 | ||||
| -rw-r--r-- | fs/cachefiles/io.c | 28 | ||||
| -rw-r--r-- | fs/cachefiles/key.c | 3 | ||||
| -rw-r--r-- | fs/cachefiles/namei.c | 218 | ||||
| -rw-r--r-- | fs/cachefiles/ondemand.c | 14 | ||||
| -rw-r--r-- | fs/cachefiles/volume.c | 11 | ||||
| -rw-r--r-- | fs/cachefiles/xattr.c | 2 |
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); } |
