Skip to content

Commit 2883aae

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull fscache fixes from Al Viro. * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: fscache: Fix dead object requeue fscache: Clear outstanding writes when disabling a cookie FS-Cache: Initialise stores_lock in netfs cookie
2 parents e387dc1 + e26bfeb commit 2883aae

File tree

4 files changed

+37
-2
lines changed

4 files changed

+37
-2
lines changed

fs/fscache/cookie.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,7 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
542542
hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) {
543543
if (invalidate)
544544
set_bit(FSCACHE_OBJECT_RETIRED, &object->flags);
545+
clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
545546
fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
546547
}
547548
} else {
@@ -560,6 +561,10 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
560561
wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t,
561562
TASK_UNINTERRUPTIBLE);
562563

564+
/* Make sure any pending writes are cancelled. */
565+
if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX)
566+
fscache_invalidate_writes(cookie);
567+
563568
/* Reset the cookie state if it wasn't relinquished */
564569
if (!test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) {
565570
atomic_inc(&cookie->n_active);

fs/fscache/netfs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
4848
cookie->flags = 1 << FSCACHE_COOKIE_ENABLED;
4949

5050
spin_lock_init(&cookie->lock);
51+
spin_lock_init(&cookie->stores_lock);
5152
INIT_HLIST_HEAD(&cookie->backing_objects);
5253

5354
/* check the netfs type is not already present */

fs/fscache/object.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ static const struct fscache_state *fscache_look_up_object(struct fscache_object
3030
static const struct fscache_state *fscache_object_available(struct fscache_object *, int);
3131
static const struct fscache_state *fscache_parent_ready(struct fscache_object *, int);
3232
static const struct fscache_state *fscache_update_object(struct fscache_object *, int);
33+
static const struct fscache_state *fscache_object_dead(struct fscache_object *, int);
3334

3435
#define __STATE_NAME(n) fscache_osm_##n
3536
#define STATE(n) (&__STATE_NAME(n))
@@ -91,7 +92,7 @@ static WORK_STATE(LOOKUP_FAILURE, "LCFL", fscache_lookup_failure);
9192
static WORK_STATE(KILL_OBJECT, "KILL", fscache_kill_object);
9293
static WORK_STATE(KILL_DEPENDENTS, "KDEP", fscache_kill_dependents);
9394
static WORK_STATE(DROP_OBJECT, "DROP", fscache_drop_object);
94-
static WORK_STATE(OBJECT_DEAD, "DEAD", (void*)2UL);
95+
static WORK_STATE(OBJECT_DEAD, "DEAD", fscache_object_dead);
9596

9697
static WAIT_STATE(WAIT_FOR_INIT, "?INI",
9798
TRANSIT_TO(INIT_OBJECT, 1 << FSCACHE_OBJECT_EV_NEW_CHILD));
@@ -229,6 +230,10 @@ static void fscache_object_sm_dispatcher(struct fscache_object *object)
229230
event = -1;
230231
if (new_state == NO_TRANSIT) {
231232
_debug("{OBJ%x} %s notrans", object->debug_id, state->name);
233+
if (unlikely(state == STATE(OBJECT_DEAD))) {
234+
_leave(" [dead]");
235+
return;
236+
}
232237
fscache_enqueue_object(object);
233238
event_mask = object->oob_event_mask;
234239
goto unmask_events;
@@ -239,7 +244,7 @@ static void fscache_object_sm_dispatcher(struct fscache_object *object)
239244
object->state = state = new_state;
240245

241246
if (state->work) {
242-
if (unlikely(state->work == ((void *)2UL))) {
247+
if (unlikely(state == STATE(OBJECT_DEAD))) {
243248
_leave(" [dead]");
244249
return;
245250
}
@@ -645,6 +650,12 @@ static const struct fscache_state *fscache_kill_object(struct fscache_object *ob
645650
fscache_mark_object_dead(object);
646651
object->oob_event_mask = 0;
647652

653+
if (test_bit(FSCACHE_OBJECT_RETIRED, &object->flags)) {
654+
/* Reject any new read/write ops and abort any that are pending. */
655+
clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
656+
fscache_cancel_all_ops(object);
657+
}
658+
648659
if (list_empty(&object->dependents) &&
649660
object->n_ops == 0 &&
650661
object->n_children == 0)
@@ -1077,3 +1088,20 @@ void fscache_object_mark_killed(struct fscache_object *object,
10771088
}
10781089
}
10791090
EXPORT_SYMBOL(fscache_object_mark_killed);
1091+
1092+
/*
1093+
* The object is dead. We can get here if an object gets queued by an event
1094+
* that would lead to its death (such as EV_KILL) when the dispatcher is
1095+
* already running (and so can be requeued) but hasn't yet cleared the event
1096+
* mask.
1097+
*/
1098+
static const struct fscache_state *fscache_object_dead(struct fscache_object *object,
1099+
int event)
1100+
{
1101+
if (!test_and_set_bit(FSCACHE_OBJECT_RUN_AFTER_DEAD,
1102+
&object->flags))
1103+
return NO_TRANSIT;
1104+
1105+
WARN(true, "FS-Cache object redispatched after death");
1106+
return NO_TRANSIT;
1107+
}

include/linux/fscache-cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ struct fscache_object {
360360
#define FSCACHE_OBJECT_IS_AVAILABLE 5 /* T if object has become active */
361361
#define FSCACHE_OBJECT_RETIRED 6 /* T if object was retired on relinquishment */
362362
#define FSCACHE_OBJECT_KILLED_BY_CACHE 7 /* T if object was killed by the cache */
363+
#define FSCACHE_OBJECT_RUN_AFTER_DEAD 8 /* T if object has been dispatched after death */
363364

364365
struct list_head cache_link; /* link in cache->object_list */
365366
struct hlist_node cookie_link; /* link in cookie->backing_objects */

0 commit comments

Comments
 (0)