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
This commit is contained in:
Коммит
2883aaea36
|
@ -542,6 +542,7 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
|
|||
hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) {
|
||||
if (invalidate)
|
||||
set_bit(FSCACHE_OBJECT_RETIRED, &object->flags);
|
||||
clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
|
||||
fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
|
||||
}
|
||||
} else {
|
||||
|
@ -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,
|
||||
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 */
|
||||
if (!test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) {
|
||||
atomic_inc(&cookie->n_active);
|
||||
|
|
|
@ -48,6 +48,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
|
|||
cookie->flags = 1 << FSCACHE_COOKIE_ENABLED;
|
||||
|
||||
spin_lock_init(&cookie->lock);
|
||||
spin_lock_init(&cookie->stores_lock);
|
||||
INIT_HLIST_HEAD(&cookie->backing_objects);
|
||||
|
||||
/* check the netfs type is not already present */
|
||||
|
|
|
@ -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_parent_ready(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(n) (&__STATE_NAME(n))
|
||||
|
@ -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_DEPENDENTS, "KDEP", fscache_kill_dependents);
|
||||
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",
|
||||
TRANSIT_TO(INIT_OBJECT, 1 << FSCACHE_OBJECT_EV_NEW_CHILD));
|
||||
|
@ -229,6 +230,10 @@ execute_work_state:
|
|||
event = -1;
|
||||
if (new_state == NO_TRANSIT) {
|
||||
_debug("{OBJ%x} %s notrans", object->debug_id, state->name);
|
||||
if (unlikely(state == STATE(OBJECT_DEAD))) {
|
||||
_leave(" [dead]");
|
||||
return;
|
||||
}
|
||||
fscache_enqueue_object(object);
|
||||
event_mask = object->oob_event_mask;
|
||||
goto unmask_events;
|
||||
|
@ -239,7 +244,7 @@ execute_work_state:
|
|||
object->state = state = new_state;
|
||||
|
||||
if (state->work) {
|
||||
if (unlikely(state->work == ((void *)2UL))) {
|
||||
if (unlikely(state == STATE(OBJECT_DEAD))) {
|
||||
_leave(" [dead]");
|
||||
return;
|
||||
}
|
||||
|
@ -645,6 +650,12 @@ static const struct fscache_state *fscache_kill_object(struct fscache_object *ob
|
|||
fscache_mark_object_dead(object);
|
||||
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) &&
|
||||
object->n_ops == 0 &&
|
||||
object->n_children == 0)
|
||||
|
@ -1077,3 +1088,20 @@ void fscache_object_mark_killed(struct fscache_object *object,
|
|||
}
|
||||
}
|
||||
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 {
|
|||
#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_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 hlist_node cookie_link; /* link in cookie->backing_objects */
|
||||
|
|
Загрузка…
Ссылка в новой задаче