Skip to content

Commit

Permalink
FS-Cache: Fix object state machine to have separate work and wait states
Browse files Browse the repository at this point in the history
Fix object state machine to have separate work and wait states as that makes
it easier to envision.

There are now three kinds of state:

 (1) Work state.  This is an execution state.  No event processing is performed
     by a work state.  The function attached to a work state returns a pointer
     indicating the next state to which the OSM should transition.  Returning
     NO_TRANSIT repeats the current state, but goes back to the scheduler
     first.

 (2) Wait state.  This is an event processing state.  No execution is
     performed by a wait state.  Wait states are just tables of "if event X
     occurs, clear it and transition to state Y".  The dispatcher returns to
     the scheduler if none of the events in which the wait state has an
     interest are currently pending.

 (3) Out-of-band state.  This is a special work state.  Transitions to normal
     states can be overridden when an unexpected event occurs (eg. I/O error).
     Instead the dispatcher disables and clears the OOB event and transits to
     the specified work state.  This then acts as an ordinary work state,
     though object->state points to the overridden destination.  Returning
     NO_TRANSIT resumes the overridden transition.

In addition, the states have names in their definitions, so there's no need for
tables of state names.  Further, the EV_REQUEUE event is no longer necessary as
that is automatic for work states.

Since the states are now separate structs rather than values in an enum, it's
not possible to use comparisons other than (non-)equality between them, so use
some object->flags to indicate what phase an object is in.

The EV_RELEASE, EV_RETIRE and EV_WITHDRAW events have been squished into one
(EV_KILL).  An object flag now carries the information about retirement.

Similarly, the RELEASING, RECYCLING and WITHDRAWING states have been merged
into an KILL_OBJECT state and additional states have been added for handling
waiting dependent objects (JUMPSTART_DEPS and KILL_DEPENDENTS).

A state has also been added for synchronising with parent object initialisation
(WAIT_FOR_PARENT) and another for initiating look up (PARENT_READY).

Signed-off-by: David Howells <dhowells@redhat.com>
Tested-By: Milosz Tanski <milosz@adfin.com>
Acked-by: Jeff Layton <jlayton@redhat.com>
  • Loading branch information
David Howells committed Jun 19, 2013
1 parent 493f7bc commit caaef69
Show file tree
Hide file tree
Showing 10 changed files with 605 additions and 577 deletions.
2 changes: 1 addition & 1 deletion fs/cachefiles/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ static void cachefiles_drop_object(struct fscache_object *_object)
#endif

/* delete retired objects */
if (object->fscache.state == FSCACHE_OBJECT_RECYCLING &&
if (test_bit(FSCACHE_OBJECT_RETIRE, &object->fscache.flags) &&
_object != cache->cache.fsdef
) {
_debug("- retire object OBJ%x", object->fscache.debug_id);
Expand Down
4 changes: 2 additions & 2 deletions fs/cachefiles/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ void __cachefiles_printk_object(struct cachefiles_object *object,
printk(KERN_ERR "%sobject: OBJ%x\n",
prefix, object->fscache.debug_id);
printk(KERN_ERR "%sobjstate=%s fl=%lx wbusy=%x ev=%lx[%lx]\n",
prefix, fscache_object_states[object->fscache.state],
prefix, object->fscache.state->name,
object->fscache.flags, work_busy(&object->fscache.work),
object->fscache.events, object->fscache.event_mask);
printk(KERN_ERR "%sops=%u inp=%u exc=%u\n",
Expand Down Expand Up @@ -127,7 +127,7 @@ static void cachefiles_mark_object_buried(struct cachefiles_cache *cache,
found_dentry:
kdebug("preemptive burial: OBJ%x [%s] %p",
object->fscache.debug_id,
fscache_object_states[object->fscache.state],
object->fscache.state->name,
dentry);

if (fscache_object_is_live(&object->fscache)) {
Expand Down
32 changes: 17 additions & 15 deletions fs/fscache/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,10 @@ int fscache_add_cache(struct fscache_cache *cache,
BUG_ON(!ifsdef);

cache->flags = 0;
ifsdef->event_mask = ULONG_MAX & ~(1 << FSCACHE_OBJECT_EV_CLEARED);
ifsdef->state = FSCACHE_OBJECT_ACTIVE;
ifsdef->event_mask =
((1 << NR_FSCACHE_OBJECT_EVENTS) - 1) &
~(1 << FSCACHE_OBJECT_EV_CLEARED);
__set_bit(FSCACHE_OBJECT_IS_AVAILABLE, &ifsdef->flags);

if (!tagname)
tagname = cache->identifier;
Expand Down Expand Up @@ -330,25 +332,25 @@ static void fscache_withdraw_all_objects(struct fscache_cache *cache,
{
struct fscache_object *object;

spin_lock(&cache->object_list_lock);

while (!list_empty(&cache->object_list)) {
object = list_entry(cache->object_list.next,
struct fscache_object, cache_link);
list_move_tail(&object->cache_link, dying_objects);
spin_lock(&cache->object_list_lock);

_debug("withdraw %p", object->cookie);
if (!list_empty(&cache->object_list)) {
object = list_entry(cache->object_list.next,
struct fscache_object, cache_link);
list_move_tail(&object->cache_link, dying_objects);

spin_lock(&object->lock);
spin_unlock(&cache->object_list_lock);
fscache_raise_event(object, FSCACHE_OBJECT_EV_WITHDRAW);
spin_unlock(&object->lock);
_debug("withdraw %p", object->cookie);

/* This must be done under object_list_lock to prevent
* a race with fscache_drop_object().
*/
fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
}

spin_unlock(&cache->object_list_lock);
cond_resched();
spin_lock(&cache->object_list_lock);
}

spin_unlock(&cache->object_list_lock);
}

/**
Expand Down
9 changes: 4 additions & 5 deletions fs/fscache/cookie.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie)

/* initiate the process of looking up all the objects in the chain
* (done by fscache_initialise_object()) */
fscache_enqueue_object(object);
fscache_raise_event(object, FSCACHE_OBJECT_EV_NEW_CHILD);

spin_unlock(&cookie->lock);

Expand Down Expand Up @@ -469,7 +469,6 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
{
struct fscache_cache *cache;
struct fscache_object *object;
unsigned long event;

fscache_stat(&fscache_n_relinquishes);
if (retire)
Expand Down Expand Up @@ -497,8 +496,6 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
fscache_wait_bit, TASK_UNINTERRUPTIBLE);
}

event = retire ? FSCACHE_OBJECT_EV_RETIRE : FSCACHE_OBJECT_EV_RELEASE;

try_again:
spin_lock(&cookie->lock);

Expand Down Expand Up @@ -533,7 +530,9 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)

cache = object->cache;
object->cookie = NULL;
fscache_raise_event(object, event);
if (retire)
set_bit(FSCACHE_OBJECT_RETIRE, &object->flags);
fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
spin_unlock(&object->lock);

if (atomic_dec_and_test(&cookie->usage))
Expand Down
8 changes: 4 additions & 4 deletions fs/fscache/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,6 @@ extern int fscache_wait_bit_interruptible(void *);
/*
* object.c
*/
extern const char fscache_object_states_short[FSCACHE_OBJECT__NSTATES][5];

extern void fscache_withdrawing_object(struct fscache_cache *,
struct fscache_object *);
extern void fscache_enqueue_object(struct fscache_object *);

/*
Expand Down Expand Up @@ -291,6 +287,10 @@ static inline void fscache_raise_event(struct fscache_object *object,
unsigned event)
{
BUG_ON(event >= NR_FSCACHE_OBJECT_EVENTS);
#if 0
printk("*** fscache_raise_event(OBJ%d{%lx},%x)\n",
object->debug_id, object->event_mask, (1 << event));
#endif
if (!test_and_set_bit(event, &object->events) &&
test_bit(event, &object->event_mask))
fscache_enqueue_object(object);
Expand Down
10 changes: 5 additions & 5 deletions fs/fscache/object-list.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v)

if ((unsigned long) v == 1) {
seq_puts(m, "OBJECT PARENT STAT CHLDN OPS OOP IPR EX READS"
" EM EV F S"
" EM EV FL S"
" | NETFS_COOKIE_DEF TY FL NETFS_DATA");
if (config & (FSCACHE_OBJLIST_CONFIG_KEY |
FSCACHE_OBJLIST_CONFIG_AUX))
Expand All @@ -193,7 +193,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v)

if ((unsigned long) v == 2) {
seq_puts(m, "======== ======== ==== ===== === === === == ====="
" == == = ="
" == == == ="
" | ================ == == ================");
if (config & (FSCACHE_OBJLIST_CONFIG_KEY |
FSCACHE_OBJLIST_CONFIG_AUX))
Expand All @@ -219,7 +219,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v)
if (~config) {
FILTER(obj->cookie,
COOKIE, NOCOOKIE);
FILTER(obj->state != FSCACHE_OBJECT_ACTIVE ||
FILTER(fscache_object_is_active(obj) ||
obj->n_ops != 0 ||
obj->n_obj_ops != 0 ||
obj->flags ||
Expand All @@ -235,10 +235,10 @@ static int fscache_objlist_show(struct seq_file *m, void *v)
}

seq_printf(m,
"%8x %8x %s %5u %3u %3u %3u %2u %5u %2lx %2lx %1lx %1x | ",
"%8x %8x %s %5u %3u %3u %3u %2u %5u %2lx %2lx %2lx %1x | ",
obj->debug_id,
obj->parent ? obj->parent->debug_id : -1,
fscache_object_states_short[obj->state],
obj->state->short_name,
obj->n_children,
obj->n_ops,
obj->n_obj_ops,
Expand Down
Loading

0 comments on commit caaef69

Please sign in to comment.