Skip to content

Commit fd3b3e0

Browse files
committed
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
2 parents 38c7b22 + 31ffa56 commit fd3b3e0

File tree

5 files changed

+17
-9
lines changed

5 files changed

+17
-9
lines changed

fs/cachefiles/namei.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,13 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
244244

245245
ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags));
246246

247-
cache->cache.ops->put_object(&xobject->fscache, cachefiles_obj_put_wait_retry);
247+
cache->cache.ops->put_object(&xobject->fscache,
248+
(enum fscache_obj_ref_trace)cachefiles_obj_put_wait_retry);
248249
goto try_again;
249250

250251
requeue:
251-
cache->cache.ops->put_object(&xobject->fscache, cachefiles_obj_put_wait_timeo);
252+
cache->cache.ops->put_object(&xobject->fscache,
253+
(enum fscache_obj_ref_trace)cachefiles_obj_put_wait_timeo);
252254
_leave(" = -ETIMEDOUT");
253255
return -ETIMEDOUT;
254256
}
@@ -336,7 +338,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
336338
try_again:
337339
/* first step is to make up a grave dentry in the graveyard */
338340
sprintf(nbuffer, "%08x%08x",
339-
(uint32_t) get_seconds(),
341+
(uint32_t) ktime_get_real_seconds(),
340342
(uint32_t) atomic_inc_return(&cache->gravecounter));
341343

342344
/* do the multiway lock magic */

fs/cachefiles/rdwr.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,10 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
535535
netpage->index, cachefiles_gfp);
536536
if (ret < 0) {
537537
if (ret == -EEXIST) {
538+
put_page(backpage);
539+
backpage = NULL;
538540
put_page(netpage);
541+
netpage = NULL;
539542
fscache_retrieval_complete(op, 1);
540543
continue;
541544
}
@@ -608,7 +611,10 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
608611
netpage->index, cachefiles_gfp);
609612
if (ret < 0) {
610613
if (ret == -EEXIST) {
614+
put_page(backpage);
615+
backpage = NULL;
611616
put_page(netpage);
617+
netpage = NULL;
612618
fscache_retrieval_complete(op, 1);
613619
continue;
614620
}
@@ -962,11 +968,8 @@ void cachefiles_uncache_page(struct fscache_object *_object, struct page *page)
962968
__releases(&object->fscache.cookie->lock)
963969
{
964970
struct cachefiles_object *object;
965-
struct cachefiles_cache *cache;
966971

967972
object = container_of(_object, struct cachefiles_object, fscache);
968-
cache = container_of(object->fscache.cache,
969-
struct cachefiles_cache, cache);
970973

971974
_enter("%p,{%lu}", object, page->index);
972975

fs/cachefiles/xattr.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,8 @@ int cachefiles_update_object_xattr(struct cachefiles_object *object,
135135
struct dentry *dentry = object->dentry;
136136
int ret;
137137

138-
ASSERT(dentry);
138+
if (!dentry)
139+
return -ESTALE;
139140

140141
_enter("%p,#%d", object, auxdata->len);
141142

fs/fscache/object.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,9 @@ static const struct fscache_state *fscache_drop_object(struct fscache_object *ob
730730

731731
if (awaken)
732732
wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
733+
if (test_and_clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags))
734+
wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP);
735+
733736

734737
/* Prevent a race with our last child, which has to signal EV_CLEARED
735738
* before dropping our spinlock.

include/linux/fscache-cache.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,7 @@ static inline void fscache_enqueue_retrieval(struct fscache_retrieval *op)
196196
static inline void fscache_retrieval_complete(struct fscache_retrieval *op,
197197
int n_pages)
198198
{
199-
atomic_sub(n_pages, &op->n_pages);
200-
if (atomic_read(&op->n_pages) <= 0)
199+
if (atomic_sub_return_relaxed(n_pages, &op->n_pages) <= 0)
201200
fscache_op_complete(&op->op, false);
202201
}
203202

0 commit comments

Comments
 (0)