Commit 2883aaea authored by Linus Torvalds's avatar Linus Torvalds

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
parents e387dc12 e26bfebd
...@@ -542,6 +542,7 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate) ...@@ -542,6 +542,7 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) { hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) {
if (invalidate) if (invalidate)
set_bit(FSCACHE_OBJECT_RETIRED, &object->flags); set_bit(FSCACHE_OBJECT_RETIRED, &object->flags);
clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL); fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
} }
} else { } else {
...@@ -560,6 +561,10 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate) ...@@ -560,6 +561,10 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t, wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t,
TASK_UNINTERRUPTIBLE); TASK_UNINTERRUPTIBLE);
/* Make sure any pending writes are cancelled. */
if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX)
fscache_invalidate_writes(cookie);
/* Reset the cookie state if it wasn't relinquished */ /* Reset the cookie state if it wasn't relinquished */
if (!test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) { if (!test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) {
atomic_inc(&cookie->n_active); atomic_inc(&cookie->n_active);
......
...@@ -48,6 +48,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs) ...@@ -48,6 +48,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
cookie->flags = 1 << FSCACHE_COOKIE_ENABLED; cookie->flags = 1 << FSCACHE_COOKIE_ENABLED;
spin_lock_init(&cookie->lock); spin_lock_init(&cookie->lock);
spin_lock_init(&cookie->stores_lock);
INIT_HLIST_HEAD(&cookie->backing_objects); INIT_HLIST_HEAD(&cookie->backing_objects);
/* check the netfs type is not already present */ /* check the netfs type is not already present */
......
...@@ -30,6 +30,7 @@ static const struct fscache_state *fscache_look_up_object(struct fscache_object ...@@ -30,6 +30,7 @@ static const struct fscache_state *fscache_look_up_object(struct fscache_object
static const struct fscache_state *fscache_object_available(struct fscache_object *, int); static const struct fscache_state *fscache_object_available(struct fscache_object *, int);
static const struct fscache_state *fscache_parent_ready(struct fscache_object *, int); static const struct fscache_state *fscache_parent_ready(struct fscache_object *, int);
static const struct fscache_state *fscache_update_object(struct fscache_object *, int); static const struct fscache_state *fscache_update_object(struct fscache_object *, int);
static const struct fscache_state *fscache_object_dead(struct fscache_object *, int);
#define __STATE_NAME(n) fscache_osm_##n #define __STATE_NAME(n) fscache_osm_##n
#define STATE(n) (&__STATE_NAME(n)) #define STATE(n) (&__STATE_NAME(n))
...@@ -91,7 +92,7 @@ static WORK_STATE(LOOKUP_FAILURE, "LCFL", fscache_lookup_failure); ...@@ -91,7 +92,7 @@ static WORK_STATE(LOOKUP_FAILURE, "LCFL", fscache_lookup_failure);
static WORK_STATE(KILL_OBJECT, "KILL", fscache_kill_object); static WORK_STATE(KILL_OBJECT, "KILL", fscache_kill_object);
static WORK_STATE(KILL_DEPENDENTS, "KDEP", fscache_kill_dependents); static WORK_STATE(KILL_DEPENDENTS, "KDEP", fscache_kill_dependents);
static WORK_STATE(DROP_OBJECT, "DROP", fscache_drop_object); static WORK_STATE(DROP_OBJECT, "DROP", fscache_drop_object);
static WORK_STATE(OBJECT_DEAD, "DEAD", (void*)2UL); static WORK_STATE(OBJECT_DEAD, "DEAD", fscache_object_dead);
static WAIT_STATE(WAIT_FOR_INIT, "?INI", static WAIT_STATE(WAIT_FOR_INIT, "?INI",
TRANSIT_TO(INIT_OBJECT, 1 << FSCACHE_OBJECT_EV_NEW_CHILD)); TRANSIT_TO(INIT_OBJECT, 1 << FSCACHE_OBJECT_EV_NEW_CHILD));
...@@ -229,6 +230,10 @@ static void fscache_object_sm_dispatcher(struct fscache_object *object) ...@@ -229,6 +230,10 @@ static void fscache_object_sm_dispatcher(struct fscache_object *object)
event = -1; event = -1;
if (new_state == NO_TRANSIT) { if (new_state == NO_TRANSIT) {
_debug("{OBJ%x} %s notrans", object->debug_id, state->name); _debug("{OBJ%x} %s notrans", object->debug_id, state->name);
if (unlikely(state == STATE(OBJECT_DEAD))) {
_leave(" [dead]");
return;
}
fscache_enqueue_object(object); fscache_enqueue_object(object);
event_mask = object->oob_event_mask; event_mask = object->oob_event_mask;
goto unmask_events; goto unmask_events;
...@@ -239,7 +244,7 @@ static void fscache_object_sm_dispatcher(struct fscache_object *object) ...@@ -239,7 +244,7 @@ static void fscache_object_sm_dispatcher(struct fscache_object *object)
object->state = state = new_state; object->state = state = new_state;
if (state->work) { if (state->work) {
if (unlikely(state->work == ((void *)2UL))) { if (unlikely(state == STATE(OBJECT_DEAD))) {
_leave(" [dead]"); _leave(" [dead]");
return; return;
} }
...@@ -645,6 +650,12 @@ static const struct fscache_state *fscache_kill_object(struct fscache_object *ob ...@@ -645,6 +650,12 @@ static const struct fscache_state *fscache_kill_object(struct fscache_object *ob
fscache_mark_object_dead(object); fscache_mark_object_dead(object);
object->oob_event_mask = 0; object->oob_event_mask = 0;
if (test_bit(FSCACHE_OBJECT_RETIRED, &object->flags)) {
/* Reject any new read/write ops and abort any that are pending. */
clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
fscache_cancel_all_ops(object);
}
if (list_empty(&object->dependents) && if (list_empty(&object->dependents) &&
object->n_ops == 0 && object->n_ops == 0 &&
object->n_children == 0) object->n_children == 0)
...@@ -1077,3 +1088,20 @@ void fscache_object_mark_killed(struct fscache_object *object, ...@@ -1077,3 +1088,20 @@ void fscache_object_mark_killed(struct fscache_object *object,
} }
} }
EXPORT_SYMBOL(fscache_object_mark_killed); EXPORT_SYMBOL(fscache_object_mark_killed);
/*
* The object is dead. We can get here if an object gets queued by an event
* that would lead to its death (such as EV_KILL) when the dispatcher is
* already running (and so can be requeued) but hasn't yet cleared the event
* mask.
*/
static const struct fscache_state *fscache_object_dead(struct fscache_object *object,
int event)
{
if (!test_and_set_bit(FSCACHE_OBJECT_RUN_AFTER_DEAD,
&object->flags))
return NO_TRANSIT;
WARN(true, "FS-Cache object redispatched after death");
return NO_TRANSIT;
}
...@@ -360,6 +360,7 @@ struct fscache_object { ...@@ -360,6 +360,7 @@ struct fscache_object {
#define FSCACHE_OBJECT_IS_AVAILABLE 5 /* T if object has become active */ #define FSCACHE_OBJECT_IS_AVAILABLE 5 /* T if object has become active */
#define FSCACHE_OBJECT_RETIRED 6 /* T if object was retired on relinquishment */ #define FSCACHE_OBJECT_RETIRED 6 /* T if object was retired on relinquishment */
#define FSCACHE_OBJECT_KILLED_BY_CACHE 7 /* T if object was killed by the cache */ #define FSCACHE_OBJECT_KILLED_BY_CACHE 7 /* T if object was killed by the cache */
#define FSCACHE_OBJECT_RUN_AFTER_DEAD 8 /* T if object has been dispatched after death */
struct list_head cache_link; /* link in cache->object_list */ struct list_head cache_link; /* link in cache->object_list */
struct hlist_node cookie_link; /* link in cookie->backing_objects */ struct hlist_node cookie_link; /* link in cookie->backing_objects */
......
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