Commit fd3b3e0e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'fscache-fixes-20181130' of...

Merge tag 'fscache-fixes-20181130' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs

Pull fscache and cachefiles fixes from David Howells:
 "Misc fixes:

   - Fix an assertion failure at fs/cachefiles/xattr.c:138 caused by a
     race between a cache object lookup failing and someone attempting
     to reenable that object, thereby triggering an update of the
     object's attributes.

   - Fix an assertion failure at fs/fscache/operation.c:449 caused by a
     split atomic subtract and atomic read that allows a race to happen.

   - Fix a leak of backing pages when simultaneously reading the same
     page from the same object from two or more threads.

   - Fix a hang due to a race between a cache object being discarded and
     the corresponding cookie being reenabled.

  There are also some minor cleanups:

   - Cast an enum value to a different enum type to prevent clang from
     generating a warning. This shouldn't cause any sort of change in
     the emitted code.

   - Use ktime_get_real_seconds() instead of get_seconds(). This is just
     used to uniquify a filename for an object to be placed in the
     graveyard. Objects placed there are deleted by cachfilesd in
     userspace immediately thereafter.

   - Remove an initialised, but otherwise unused variable. This should
     have been entirely optimised away anyway"

* tag 'fscache-fixes-20181130' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs:
  fscache, cachefiles: remove redundant variable 'cache'
  cachefiles: avoid deprecated get_seconds()
  cachefiles: Explicitly cast enumerated type in put_object
  fscache: fix race between enablement and dropping of object
  cachefiles: Fix page leak in cachefiles_read_backing_file while vmscan is active
  fscache: Fix race in fscache_op_complete() due to split atomic_sub & read
  cachefiles: Fix an assertion failure when trying to update a failed object
parents 38c7b224 31ffa563
...@@ -244,11 +244,13 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache, ...@@ -244,11 +244,13 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags)); ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags));
cache->cache.ops->put_object(&xobject->fscache, cachefiles_obj_put_wait_retry); cache->cache.ops->put_object(&xobject->fscache,
(enum fscache_obj_ref_trace)cachefiles_obj_put_wait_retry);
goto try_again; goto try_again;
requeue: requeue:
cache->cache.ops->put_object(&xobject->fscache, cachefiles_obj_put_wait_timeo); cache->cache.ops->put_object(&xobject->fscache,
(enum fscache_obj_ref_trace)cachefiles_obj_put_wait_timeo);
_leave(" = -ETIMEDOUT"); _leave(" = -ETIMEDOUT");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
...@@ -336,7 +338,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache, ...@@ -336,7 +338,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
try_again: try_again:
/* first step is to make up a grave dentry in the graveyard */ /* first step is to make up a grave dentry in the graveyard */
sprintf(nbuffer, "%08x%08x", sprintf(nbuffer, "%08x%08x",
(uint32_t) get_seconds(), (uint32_t) ktime_get_real_seconds(),
(uint32_t) atomic_inc_return(&cache->gravecounter)); (uint32_t) atomic_inc_return(&cache->gravecounter));
/* do the multiway lock magic */ /* do the multiway lock magic */
......
...@@ -535,7 +535,10 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object, ...@@ -535,7 +535,10 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
netpage->index, cachefiles_gfp); netpage->index, cachefiles_gfp);
if (ret < 0) { if (ret < 0) {
if (ret == -EEXIST) { if (ret == -EEXIST) {
put_page(backpage);
backpage = NULL;
put_page(netpage); put_page(netpage);
netpage = NULL;
fscache_retrieval_complete(op, 1); fscache_retrieval_complete(op, 1);
continue; continue;
} }
...@@ -608,7 +611,10 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object, ...@@ -608,7 +611,10 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
netpage->index, cachefiles_gfp); netpage->index, cachefiles_gfp);
if (ret < 0) { if (ret < 0) {
if (ret == -EEXIST) { if (ret == -EEXIST) {
put_page(backpage);
backpage = NULL;
put_page(netpage); put_page(netpage);
netpage = NULL;
fscache_retrieval_complete(op, 1); fscache_retrieval_complete(op, 1);
continue; continue;
} }
...@@ -962,11 +968,8 @@ void cachefiles_uncache_page(struct fscache_object *_object, struct page *page) ...@@ -962,11 +968,8 @@ void cachefiles_uncache_page(struct fscache_object *_object, struct page *page)
__releases(&object->fscache.cookie->lock) __releases(&object->fscache.cookie->lock)
{ {
struct cachefiles_object *object; struct cachefiles_object *object;
struct cachefiles_cache *cache;
object = container_of(_object, struct cachefiles_object, fscache); object = container_of(_object, struct cachefiles_object, fscache);
cache = container_of(object->fscache.cache,
struct cachefiles_cache, cache);
_enter("%p,{%lu}", object, page->index); _enter("%p,{%lu}", object, page->index);
......
...@@ -135,7 +135,8 @@ int cachefiles_update_object_xattr(struct cachefiles_object *object, ...@@ -135,7 +135,8 @@ int cachefiles_update_object_xattr(struct cachefiles_object *object,
struct dentry *dentry = object->dentry; struct dentry *dentry = object->dentry;
int ret; int ret;
ASSERT(dentry); if (!dentry)
return -ESTALE;
_enter("%p,#%d", object, auxdata->len); _enter("%p,#%d", object, auxdata->len);
......
...@@ -730,6 +730,9 @@ static const struct fscache_state *fscache_drop_object(struct fscache_object *ob ...@@ -730,6 +730,9 @@ static const struct fscache_state *fscache_drop_object(struct fscache_object *ob
if (awaken) if (awaken)
wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING); wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
if (test_and_clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags))
wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP);
/* Prevent a race with our last child, which has to signal EV_CLEARED /* Prevent a race with our last child, which has to signal EV_CLEARED
* before dropping our spinlock. * before dropping our spinlock.
......
...@@ -196,8 +196,7 @@ static inline void fscache_enqueue_retrieval(struct fscache_retrieval *op) ...@@ -196,8 +196,7 @@ static inline void fscache_enqueue_retrieval(struct fscache_retrieval *op)
static inline void fscache_retrieval_complete(struct fscache_retrieval *op, static inline void fscache_retrieval_complete(struct fscache_retrieval *op,
int n_pages) int n_pages)
{ {
atomic_sub(n_pages, &op->n_pages); if (atomic_sub_return_relaxed(n_pages, &op->n_pages) <= 0)
if (atomic_read(&op->n_pages) <= 0)
fscache_op_complete(&op->op, false); fscache_op_complete(&op->op, false);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment