Skip to content

Commit e5524c2

Browse files
committed
Merge tag 'fscache-fixes-20220708' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
Pull fscache fixes from David Howells: - Fix a check in fscache_wait_on_volume_collision() in which the polarity is reversed. It should complain if a volume is still marked acquisition-pending after 20s, but instead complains if the mark has been cleared (ie. the condition has cleared). Also switch an open-coded test of the ACQUIRE_PENDING volume flag to use the helper function for consistency. - Not a fix per se, but neaten the code by using a helper to check for the DROPPED state. - Fix cachefiles's support for erofs to only flush requests associated with a released control file, not all requests. - Fix a race between one process invalidating an object in the cache and another process trying to look it up. * tag 'fscache-fixes-20220708' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs: fscache: Fix invalidation/lookup race cachefiles: narrow the scope of flushed requests when releasing fd fscache: Introduce fscache_cookie_is_dropped() fscache: Fix if condition in fscache_wait_on_volume_collision()
2 parents 525496a + 85e4ea1 commit e5524c2

File tree

4 files changed

+27
-7
lines changed

4 files changed

+27
-7
lines changed

fs/cachefiles/ondemand.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ static int cachefiles_ondemand_fd_release(struct inode *inode,
2121
* anon_fd.
2222
*/
2323
xas_for_each(&xas, req, ULONG_MAX) {
24-
if (req->msg.opcode == CACHEFILES_OP_READ) {
24+
if (req->msg.object_id == object_id &&
25+
req->msg.opcode == CACHEFILES_OP_READ) {
2526
req->error = -EIO;
2627
complete(&req->done);
2728
xas_store(&xas, NULL);

fs/fscache/cookie.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -372,17 +372,22 @@ static struct fscache_cookie *fscache_alloc_cookie(
372372
return NULL;
373373
}
374374

375+
static inline bool fscache_cookie_is_dropped(struct fscache_cookie *cookie)
376+
{
377+
return READ_ONCE(cookie->state) == FSCACHE_COOKIE_STATE_DROPPED;
378+
}
379+
375380
static void fscache_wait_on_collision(struct fscache_cookie *candidate,
376381
struct fscache_cookie *wait_for)
377382
{
378383
enum fscache_cookie_state *statep = &wait_for->state;
379384

380-
wait_var_event_timeout(statep, READ_ONCE(*statep) == FSCACHE_COOKIE_STATE_DROPPED,
385+
wait_var_event_timeout(statep, fscache_cookie_is_dropped(wait_for),
381386
20 * HZ);
382-
if (READ_ONCE(*statep) != FSCACHE_COOKIE_STATE_DROPPED) {
387+
if (!fscache_cookie_is_dropped(wait_for)) {
383388
pr_notice("Potential collision c=%08x old: c=%08x",
384389
candidate->debug_id, wait_for->debug_id);
385-
wait_var_event(statep, READ_ONCE(*statep) == FSCACHE_COOKIE_STATE_DROPPED);
390+
wait_var_event(statep, fscache_cookie_is_dropped(wait_for));
386391
}
387392
}
388393

@@ -517,7 +522,14 @@ static void fscache_perform_lookup(struct fscache_cookie *cookie)
517522
}
518523

519524
fscache_see_cookie(cookie, fscache_cookie_see_active);
520-
fscache_set_cookie_state(cookie, FSCACHE_COOKIE_STATE_ACTIVE);
525+
spin_lock(&cookie->lock);
526+
if (test_and_clear_bit(FSCACHE_COOKIE_DO_INVALIDATE, &cookie->flags))
527+
__fscache_set_cookie_state(cookie,
528+
FSCACHE_COOKIE_STATE_INVALIDATING);
529+
else
530+
__fscache_set_cookie_state(cookie, FSCACHE_COOKIE_STATE_ACTIVE);
531+
spin_unlock(&cookie->lock);
532+
wake_up_cookie_state(cookie);
521533
trace = fscache_access_lookup_cookie_end;
522534

523535
out:
@@ -752,6 +764,9 @@ static void fscache_cookie_state_machine(struct fscache_cookie *cookie)
752764
spin_lock(&cookie->lock);
753765
}
754766

767+
if (test_and_clear_bit(FSCACHE_COOKIE_DO_INVALIDATE, &cookie->flags))
768+
fscache_end_cookie_access(cookie, fscache_access_invalidate_cookie_end);
769+
755770
switch (state) {
756771
case FSCACHE_COOKIE_STATE_RELINQUISHING:
757772
fscache_see_cookie(cookie, fscache_cookie_see_relinquish);
@@ -1048,6 +1063,9 @@ void __fscache_invalidate(struct fscache_cookie *cookie,
10481063
return;
10491064

10501065
case FSCACHE_COOKIE_STATE_LOOKING_UP:
1066+
__fscache_begin_cookie_access(cookie, fscache_access_invalidate_cookie);
1067+
set_bit(FSCACHE_COOKIE_DO_INVALIDATE, &cookie->flags);
1068+
fallthrough;
10511069
case FSCACHE_COOKIE_STATE_CREATING:
10521070
spin_unlock(&cookie->lock);
10531071
_leave(" [look %x]", cookie->inval_counter);

fs/fscache/volume.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ static void fscache_wait_on_volume_collision(struct fscache_volume *candidate,
143143
{
144144
wait_var_event_timeout(&candidate->flags,
145145
!fscache_is_acquire_pending(candidate), 20 * HZ);
146-
if (!fscache_is_acquire_pending(candidate)) {
146+
if (fscache_is_acquire_pending(candidate)) {
147147
pr_notice("Potential volume collision new=%08x old=%08x",
148148
candidate->debug_id, collidee_debug_id);
149149
fscache_stat(&fscache_n_volumes_collision);
@@ -182,7 +182,7 @@ static bool fscache_hash_volume(struct fscache_volume *candidate)
182182
hlist_bl_add_head(&candidate->hash_link, h);
183183
hlist_bl_unlock(h);
184184

185-
if (test_bit(FSCACHE_VOLUME_ACQUIRE_PENDING, &candidate->flags))
185+
if (fscache_is_acquire_pending(candidate))
186186
fscache_wait_on_volume_collision(candidate, collidee_debug_id);
187187
return true;
188188

include/linux/fscache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ struct fscache_cookie {
130130
#define FSCACHE_COOKIE_DO_PREP_TO_WRITE 12 /* T if cookie needs write preparation */
131131
#define FSCACHE_COOKIE_HAVE_DATA 13 /* T if this cookie has data stored */
132132
#define FSCACHE_COOKIE_IS_HASHED 14 /* T if this cookie is hashed */
133+
#define FSCACHE_COOKIE_DO_INVALIDATE 15 /* T if cookie needs invalidation */
133134

134135
enum fscache_cookie_state state;
135136
u8 advice; /* FSCACHE_ADV_* */

0 commit comments

Comments
 (0)