forked from Minki/linux
FS-Cache: Fix object state machine to have separate work and wait states
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>
This commit is contained in:
parent
493f7bc114
commit
caaef6900b
@ -263,7 +263,7 @@ static void cachefiles_drop_object(struct fscache_object *_object)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* delete retired objects */
|
/* delete retired objects */
|
||||||
if (object->fscache.state == FSCACHE_OBJECT_RECYCLING &&
|
if (test_bit(FSCACHE_OBJECT_RETIRE, &object->fscache.flags) &&
|
||||||
_object != cache->cache.fsdef
|
_object != cache->cache.fsdef
|
||||||
) {
|
) {
|
||||||
_debug("- retire object OBJ%x", object->fscache.debug_id);
|
_debug("- retire object OBJ%x", object->fscache.debug_id);
|
||||||
|
@ -38,7 +38,7 @@ void __cachefiles_printk_object(struct cachefiles_object *object,
|
|||||||
printk(KERN_ERR "%sobject: OBJ%x\n",
|
printk(KERN_ERR "%sobject: OBJ%x\n",
|
||||||
prefix, object->fscache.debug_id);
|
prefix, object->fscache.debug_id);
|
||||||
printk(KERN_ERR "%sobjstate=%s fl=%lx wbusy=%x ev=%lx[%lx]\n",
|
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.flags, work_busy(&object->fscache.work),
|
||||||
object->fscache.events, object->fscache.event_mask);
|
object->fscache.events, object->fscache.event_mask);
|
||||||
printk(KERN_ERR "%sops=%u inp=%u exc=%u\n",
|
printk(KERN_ERR "%sops=%u inp=%u exc=%u\n",
|
||||||
@ -127,7 +127,7 @@ static void cachefiles_mark_object_buried(struct cachefiles_cache *cache,
|
|||||||
found_dentry:
|
found_dentry:
|
||||||
kdebug("preemptive burial: OBJ%x [%s] %p",
|
kdebug("preemptive burial: OBJ%x [%s] %p",
|
||||||
object->fscache.debug_id,
|
object->fscache.debug_id,
|
||||||
fscache_object_states[object->fscache.state],
|
object->fscache.state->name,
|
||||||
dentry);
|
dentry);
|
||||||
|
|
||||||
if (fscache_object_is_live(&object->fscache)) {
|
if (fscache_object_is_live(&object->fscache)) {
|
||||||
|
@ -224,8 +224,10 @@ int fscache_add_cache(struct fscache_cache *cache,
|
|||||||
BUG_ON(!ifsdef);
|
BUG_ON(!ifsdef);
|
||||||
|
|
||||||
cache->flags = 0;
|
cache->flags = 0;
|
||||||
ifsdef->event_mask = ULONG_MAX & ~(1 << FSCACHE_OBJECT_EV_CLEARED);
|
ifsdef->event_mask =
|
||||||
ifsdef->state = FSCACHE_OBJECT_ACTIVE;
|
((1 << NR_FSCACHE_OBJECT_EVENTS) - 1) &
|
||||||
|
~(1 << FSCACHE_OBJECT_EV_CLEARED);
|
||||||
|
__set_bit(FSCACHE_OBJECT_IS_AVAILABLE, &ifsdef->flags);
|
||||||
|
|
||||||
if (!tagname)
|
if (!tagname)
|
||||||
tagname = cache->identifier;
|
tagname = cache->identifier;
|
||||||
@ -330,25 +332,25 @@ static void fscache_withdraw_all_objects(struct fscache_cache *cache,
|
|||||||
{
|
{
|
||||||
struct fscache_object *object;
|
struct fscache_object *object;
|
||||||
|
|
||||||
spin_lock(&cache->object_list_lock);
|
|
||||||
|
|
||||||
while (!list_empty(&cache->object_list)) {
|
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);
|
|
||||||
|
|
||||||
_debug("withdraw %p", object->cookie);
|
|
||||||
|
|
||||||
spin_lock(&object->lock);
|
|
||||||
spin_unlock(&cache->object_list_lock);
|
|
||||||
fscache_raise_event(object, FSCACHE_OBJECT_EV_WITHDRAW);
|
|
||||||
spin_unlock(&object->lock);
|
|
||||||
|
|
||||||
cond_resched();
|
|
||||||
spin_lock(&cache->object_list_lock);
|
spin_lock(&cache->object_list_lock);
|
||||||
}
|
|
||||||
|
|
||||||
spin_unlock(&cache->object_list_lock);
|
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);
|
||||||
|
|
||||||
|
_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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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
|
/* initiate the process of looking up all the objects in the chain
|
||||||
* (done by fscache_initialise_object()) */
|
* (done by fscache_initialise_object()) */
|
||||||
fscache_enqueue_object(object);
|
fscache_raise_event(object, FSCACHE_OBJECT_EV_NEW_CHILD);
|
||||||
|
|
||||||
spin_unlock(&cookie->lock);
|
spin_unlock(&cookie->lock);
|
||||||
|
|
||||||
@ -469,7 +469,6 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
|
|||||||
{
|
{
|
||||||
struct fscache_cache *cache;
|
struct fscache_cache *cache;
|
||||||
struct fscache_object *object;
|
struct fscache_object *object;
|
||||||
unsigned long event;
|
|
||||||
|
|
||||||
fscache_stat(&fscache_n_relinquishes);
|
fscache_stat(&fscache_n_relinquishes);
|
||||||
if (retire)
|
if (retire)
|
||||||
@ -497,8 +496,6 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
|
|||||||
fscache_wait_bit, TASK_UNINTERRUPTIBLE);
|
fscache_wait_bit, TASK_UNINTERRUPTIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
event = retire ? FSCACHE_OBJECT_EV_RETIRE : FSCACHE_OBJECT_EV_RELEASE;
|
|
||||||
|
|
||||||
try_again:
|
try_again:
|
||||||
spin_lock(&cookie->lock);
|
spin_lock(&cookie->lock);
|
||||||
|
|
||||||
@ -533,7 +530,9 @@ try_again:
|
|||||||
|
|
||||||
cache = object->cache;
|
cache = object->cache;
|
||||||
object->cookie = NULL;
|
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);
|
spin_unlock(&object->lock);
|
||||||
|
|
||||||
if (atomic_dec_and_test(&cookie->usage))
|
if (atomic_dec_and_test(&cookie->usage))
|
||||||
|
@ -97,10 +97,6 @@ extern int fscache_wait_bit_interruptible(void *);
|
|||||||
/*
|
/*
|
||||||
* object.c
|
* 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 *);
|
extern void fscache_enqueue_object(struct fscache_object *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -291,6 +287,10 @@ static inline void fscache_raise_event(struct fscache_object *object,
|
|||||||
unsigned event)
|
unsigned event)
|
||||||
{
|
{
|
||||||
BUG_ON(event >= NR_FSCACHE_OBJECT_EVENTS);
|
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) &&
|
if (!test_and_set_bit(event, &object->events) &&
|
||||||
test_bit(event, &object->event_mask))
|
test_bit(event, &object->event_mask))
|
||||||
fscache_enqueue_object(object);
|
fscache_enqueue_object(object);
|
||||||
|
@ -174,7 +174,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v)
|
|||||||
|
|
||||||
if ((unsigned long) v == 1) {
|
if ((unsigned long) v == 1) {
|
||||||
seq_puts(m, "OBJECT PARENT STAT CHLDN OPS OOP IPR EX READS"
|
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");
|
" | NETFS_COOKIE_DEF TY FL NETFS_DATA");
|
||||||
if (config & (FSCACHE_OBJLIST_CONFIG_KEY |
|
if (config & (FSCACHE_OBJLIST_CONFIG_KEY |
|
||||||
FSCACHE_OBJLIST_CONFIG_AUX))
|
FSCACHE_OBJLIST_CONFIG_AUX))
|
||||||
@ -193,7 +193,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v)
|
|||||||
|
|
||||||
if ((unsigned long) v == 2) {
|
if ((unsigned long) v == 2) {
|
||||||
seq_puts(m, "======== ======== ==== ===== === === === == ====="
|
seq_puts(m, "======== ======== ==== ===== === === === == ====="
|
||||||
" == == = ="
|
" == == == ="
|
||||||
" | ================ == == ================");
|
" | ================ == == ================");
|
||||||
if (config & (FSCACHE_OBJLIST_CONFIG_KEY |
|
if (config & (FSCACHE_OBJLIST_CONFIG_KEY |
|
||||||
FSCACHE_OBJLIST_CONFIG_AUX))
|
FSCACHE_OBJLIST_CONFIG_AUX))
|
||||||
@ -219,7 +219,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v)
|
|||||||
if (~config) {
|
if (~config) {
|
||||||
FILTER(obj->cookie,
|
FILTER(obj->cookie,
|
||||||
COOKIE, NOCOOKIE);
|
COOKIE, NOCOOKIE);
|
||||||
FILTER(obj->state != FSCACHE_OBJECT_ACTIVE ||
|
FILTER(fscache_object_is_active(obj) ||
|
||||||
obj->n_ops != 0 ||
|
obj->n_ops != 0 ||
|
||||||
obj->n_obj_ops != 0 ||
|
obj->n_obj_ops != 0 ||
|
||||||
obj->flags ||
|
obj->flags ||
|
||||||
@ -235,10 +235,10 @@ static int fscache_objlist_show(struct seq_file *m, void *v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
seq_printf(m,
|
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->debug_id,
|
||||||
obj->parent ? obj->parent->debug_id : -1,
|
obj->parent ? obj->parent->debug_id : -1,
|
||||||
fscache_object_states_short[obj->state],
|
obj->state->short_name,
|
||||||
obj->n_children,
|
obj->n_children,
|
||||||
obj->n_ops,
|
obj->n_ops,
|
||||||
obj->n_obj_ops,
|
obj->n_obj_ops,
|
||||||
|
1072
fs/fscache/object.c
1072
fs/fscache/object.c
File diff suppressed because it is too large
Load Diff
@ -119,7 +119,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
|
|||||||
/* need to issue a new write op after this */
|
/* need to issue a new write op after this */
|
||||||
clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
|
clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else if (object->state == FSCACHE_OBJECT_CREATING) {
|
} else if (test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)) {
|
||||||
op->object = object;
|
op->object = object;
|
||||||
object->n_ops++;
|
object->n_ops++;
|
||||||
object->n_exclusive++; /* reads and writes must wait */
|
object->n_exclusive++; /* reads and writes must wait */
|
||||||
@ -144,7 +144,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
|
|||||||
*/
|
*/
|
||||||
static void fscache_report_unexpected_submission(struct fscache_object *object,
|
static void fscache_report_unexpected_submission(struct fscache_object *object,
|
||||||
struct fscache_operation *op,
|
struct fscache_operation *op,
|
||||||
unsigned long ostate)
|
const struct fscache_state *ostate)
|
||||||
{
|
{
|
||||||
static bool once_only;
|
static bool once_only;
|
||||||
struct fscache_operation *p;
|
struct fscache_operation *p;
|
||||||
@ -155,11 +155,8 @@ static void fscache_report_unexpected_submission(struct fscache_object *object,
|
|||||||
once_only = true;
|
once_only = true;
|
||||||
|
|
||||||
kdebug("unexpected submission OP%x [OBJ%x %s]",
|
kdebug("unexpected submission OP%x [OBJ%x %s]",
|
||||||
op->debug_id, object->debug_id,
|
op->debug_id, object->debug_id, object->state->name);
|
||||||
fscache_object_states[object->state]);
|
kdebug("objstate=%s [%s]", object->state->name, ostate->name);
|
||||||
kdebug("objstate=%s [%s]",
|
|
||||||
fscache_object_states[object->state],
|
|
||||||
fscache_object_states[ostate]);
|
|
||||||
kdebug("objflags=%lx", object->flags);
|
kdebug("objflags=%lx", object->flags);
|
||||||
kdebug("objevent=%lx [%lx]", object->events, object->event_mask);
|
kdebug("objevent=%lx [%lx]", object->events, object->event_mask);
|
||||||
kdebug("ops=%u inp=%u exc=%u",
|
kdebug("ops=%u inp=%u exc=%u",
|
||||||
@ -190,7 +187,7 @@ static void fscache_report_unexpected_submission(struct fscache_object *object,
|
|||||||
int fscache_submit_op(struct fscache_object *object,
|
int fscache_submit_op(struct fscache_object *object,
|
||||||
struct fscache_operation *op)
|
struct fscache_operation *op)
|
||||||
{
|
{
|
||||||
unsigned long ostate;
|
const struct fscache_state *ostate;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
_enter("{OBJ%x OP%x},{%u}",
|
_enter("{OBJ%x OP%x},{%u}",
|
||||||
@ -226,16 +223,14 @@ int fscache_submit_op(struct fscache_object *object,
|
|||||||
fscache_run_op(object, op);
|
fscache_run_op(object, op);
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else if (object->state == FSCACHE_OBJECT_CREATING) {
|
} else if (test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)) {
|
||||||
op->object = object;
|
op->object = object;
|
||||||
object->n_ops++;
|
object->n_ops++;
|
||||||
atomic_inc(&op->usage);
|
atomic_inc(&op->usage);
|
||||||
list_add_tail(&op->pend_link, &object->pending_ops);
|
list_add_tail(&op->pend_link, &object->pending_ops);
|
||||||
fscache_stat(&fscache_n_op_pend);
|
fscache_stat(&fscache_n_op_pend);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else if (object->state == FSCACHE_OBJECT_DYING ||
|
} else if (fscache_object_is_dying(object)) {
|
||||||
object->state == FSCACHE_OBJECT_LC_DYING ||
|
|
||||||
object->state == FSCACHE_OBJECT_WITHDRAWING) {
|
|
||||||
fscache_stat(&fscache_n_op_rejected);
|
fscache_stat(&fscache_n_op_rejected);
|
||||||
op->state = FSCACHE_OP_ST_CANCELLED;
|
op->state = FSCACHE_OP_ST_CANCELLED;
|
||||||
ret = -ENOBUFS;
|
ret = -ENOBUFS;
|
||||||
@ -266,13 +261,14 @@ void fscache_abort_object(struct fscache_object *object)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* jump start the operation processing on an object
|
* jump start the operation processing on an object
|
||||||
* - caller must hold object->lock
|
|
||||||
*/
|
*/
|
||||||
void fscache_start_operations(struct fscache_object *object)
|
void fscache_start_operations(struct fscache_object *object)
|
||||||
{
|
{
|
||||||
struct fscache_operation *op;
|
struct fscache_operation *op;
|
||||||
bool stop = false;
|
bool stop = false;
|
||||||
|
|
||||||
|
ASSERT(spin_is_locked(&object->lock));
|
||||||
|
|
||||||
while (!list_empty(&object->pending_ops) && !stop) {
|
while (!list_empty(&object->pending_ops) && !stop) {
|
||||||
op = list_entry(object->pending_ops.next,
|
op = list_entry(object->pending_ops.next,
|
||||||
struct fscache_operation, pend_link);
|
struct fscache_operation, pend_link);
|
||||||
|
@ -408,7 +408,7 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
|
|||||||
object = hlist_entry(cookie->backing_objects.first,
|
object = hlist_entry(cookie->backing_objects.first,
|
||||||
struct fscache_object, cookie_link);
|
struct fscache_object, cookie_link);
|
||||||
|
|
||||||
ASSERTCMP(object->state, >, FSCACHE_OBJECT_LOOKING_UP);
|
ASSERT(test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags));
|
||||||
|
|
||||||
atomic_inc(&object->n_reads);
|
atomic_inc(&object->n_reads);
|
||||||
__set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags);
|
__set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags);
|
||||||
@ -729,8 +729,9 @@ static void fscache_write_op(struct fscache_operation *_op)
|
|||||||
*/
|
*/
|
||||||
spin_unlock(&object->lock);
|
spin_unlock(&object->lock);
|
||||||
fscache_op_complete(&op->op, false);
|
fscache_op_complete(&op->op, false);
|
||||||
_leave(" [cancel] op{f=%lx s=%u} obj{s=%u f=%lx}",
|
_leave(" [cancel] op{f=%lx s=%u} obj{s=%s f=%lx}",
|
||||||
_op->flags, _op->state, object->state, object->flags);
|
_op->flags, _op->state, object->state->short_name,
|
||||||
|
object->flags);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -833,14 +834,12 @@ void fscache_invalidate_writes(struct fscache_cookie *cookie)
|
|||||||
* (1) negative lookup, object not yet created (FSCACHE_COOKIE_CREATING is
|
* (1) negative lookup, object not yet created (FSCACHE_COOKIE_CREATING is
|
||||||
* set)
|
* set)
|
||||||
*
|
*
|
||||||
* (a) no writes yet (set FSCACHE_COOKIE_PENDING_FILL and queue deferred
|
* (a) no writes yet
|
||||||
* fill op)
|
|
||||||
*
|
*
|
||||||
* (b) writes deferred till post-creation (mark page for writing and
|
* (b) writes deferred till post-creation (mark page for writing and
|
||||||
* return immediately)
|
* return immediately)
|
||||||
*
|
*
|
||||||
* (2) negative lookup, object created, initial fill being made from netfs
|
* (2) negative lookup, object created, initial fill being made from netfs
|
||||||
* (FSCACHE_COOKIE_INITIAL_FILL is set)
|
|
||||||
*
|
*
|
||||||
* (a) fill point not yet reached this page (mark page for writing and
|
* (a) fill point not yet reached this page (mark page for writing and
|
||||||
* return)
|
* return)
|
||||||
|
@ -328,11 +328,9 @@ struct fscache_cookie {
|
|||||||
#define FSCACHE_COOKIE_LOOKING_UP 0 /* T if non-index cookie being looked up still */
|
#define FSCACHE_COOKIE_LOOKING_UP 0 /* T if non-index cookie being looked up still */
|
||||||
#define FSCACHE_COOKIE_CREATING 1 /* T if non-index object being created still */
|
#define FSCACHE_COOKIE_CREATING 1 /* T if non-index object being created still */
|
||||||
#define FSCACHE_COOKIE_NO_DATA_YET 2 /* T if new object with no cached data yet */
|
#define FSCACHE_COOKIE_NO_DATA_YET 2 /* T if new object with no cached data yet */
|
||||||
#define FSCACHE_COOKIE_PENDING_FILL 3 /* T if pending initial fill on object */
|
#define FSCACHE_COOKIE_UNAVAILABLE 3 /* T if cookie is unavailable (error, etc) */
|
||||||
#define FSCACHE_COOKIE_FILLING 4 /* T if filling object incrementally */
|
#define FSCACHE_COOKIE_WAITING_ON_READS 4 /* T if cookie is waiting on reads */
|
||||||
#define FSCACHE_COOKIE_UNAVAILABLE 5 /* T if cookie is unavailable (error, etc) */
|
#define FSCACHE_COOKIE_INVALIDATING 5 /* T if cookie is being invalidated */
|
||||||
#define FSCACHE_COOKIE_WAITING_ON_READS 6 /* T if cookie is waiting on reads */
|
|
||||||
#define FSCACHE_COOKIE_INVALIDATING 7 /* T if cookie is being invalidated */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct fscache_cookie fscache_fsdef_index;
|
extern struct fscache_cookie fscache_fsdef_index;
|
||||||
@ -341,45 +339,40 @@ extern struct fscache_cookie fscache_fsdef_index;
|
|||||||
* Event list for fscache_object::{event_mask,events}
|
* Event list for fscache_object::{event_mask,events}
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
FSCACHE_OBJECT_EV_REQUEUE, /* T if object should be requeued */
|
FSCACHE_OBJECT_EV_NEW_CHILD, /* T if object has a new child */
|
||||||
|
FSCACHE_OBJECT_EV_PARENT_READY, /* T if object's parent is ready */
|
||||||
FSCACHE_OBJECT_EV_UPDATE, /* T if object should be updated */
|
FSCACHE_OBJECT_EV_UPDATE, /* T if object should be updated */
|
||||||
FSCACHE_OBJECT_EV_INVALIDATE, /* T if cache requested object invalidation */
|
FSCACHE_OBJECT_EV_INVALIDATE, /* T if cache requested object invalidation */
|
||||||
FSCACHE_OBJECT_EV_CLEARED, /* T if accessors all gone */
|
FSCACHE_OBJECT_EV_CLEARED, /* T if accessors all gone */
|
||||||
FSCACHE_OBJECT_EV_ERROR, /* T if fatal error occurred during processing */
|
FSCACHE_OBJECT_EV_ERROR, /* T if fatal error occurred during processing */
|
||||||
FSCACHE_OBJECT_EV_RELEASE, /* T if netfs requested object release */
|
FSCACHE_OBJECT_EV_KILL, /* T if netfs relinquished or cache withdrew object */
|
||||||
FSCACHE_OBJECT_EV_RETIRE, /* T if netfs requested object retirement */
|
|
||||||
FSCACHE_OBJECT_EV_WITHDRAW, /* T if cache requested object withdrawal */
|
|
||||||
NR_FSCACHE_OBJECT_EVENTS
|
NR_FSCACHE_OBJECT_EVENTS
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FSCACHE_OBJECT_EVENTS_MASK ((1UL << NR_FSCACHE_OBJECT_EVENTS) - 1)
|
#define FSCACHE_OBJECT_EVENTS_MASK ((1UL << NR_FSCACHE_OBJECT_EVENTS) - 1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* States for object state machine.
|
||||||
|
*/
|
||||||
|
struct fscache_transition {
|
||||||
|
unsigned long events;
|
||||||
|
const struct fscache_state *transit_to;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fscache_state {
|
||||||
|
char name[24];
|
||||||
|
char short_name[8];
|
||||||
|
const struct fscache_state *(*work)(struct fscache_object *object,
|
||||||
|
int event);
|
||||||
|
const struct fscache_transition transitions[];
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* on-disk cache file or index handle
|
* on-disk cache file or index handle
|
||||||
*/
|
*/
|
||||||
struct fscache_object {
|
struct fscache_object {
|
||||||
enum fscache_object_state {
|
const struct fscache_state *state; /* Object state machine state */
|
||||||
FSCACHE_OBJECT_INIT, /* object in initial unbound state */
|
const struct fscache_transition *oob_table; /* OOB state transition table */
|
||||||
FSCACHE_OBJECT_LOOKING_UP, /* looking up object */
|
|
||||||
FSCACHE_OBJECT_CREATING, /* creating object */
|
|
||||||
|
|
||||||
/* active states */
|
|
||||||
FSCACHE_OBJECT_AVAILABLE, /* cleaning up object after creation */
|
|
||||||
FSCACHE_OBJECT_ACTIVE, /* object is usable */
|
|
||||||
FSCACHE_OBJECT_INVALIDATING, /* object is invalidating */
|
|
||||||
FSCACHE_OBJECT_UPDATING, /* object is updating */
|
|
||||||
|
|
||||||
/* terminal states */
|
|
||||||
FSCACHE_OBJECT_DYING, /* object waiting for accessors to finish */
|
|
||||||
FSCACHE_OBJECT_LC_DYING, /* object cleaning up after lookup/create */
|
|
||||||
FSCACHE_OBJECT_ABORT_INIT, /* abort the init state */
|
|
||||||
FSCACHE_OBJECT_RELEASING, /* releasing object */
|
|
||||||
FSCACHE_OBJECT_RECYCLING, /* retiring object */
|
|
||||||
FSCACHE_OBJECT_WITHDRAWING, /* withdrawing object */
|
|
||||||
FSCACHE_OBJECT_DEAD, /* object is now dead */
|
|
||||||
FSCACHE_OBJECT__NSTATES
|
|
||||||
} state;
|
|
||||||
|
|
||||||
int debug_id; /* debugging ID */
|
int debug_id; /* debugging ID */
|
||||||
int n_children; /* number of child objects */
|
int n_children; /* number of child objects */
|
||||||
int n_ops; /* number of extant ops on object */
|
int n_ops; /* number of extant ops on object */
|
||||||
@ -390,6 +383,7 @@ struct fscache_object {
|
|||||||
spinlock_t lock; /* state and operations lock */
|
spinlock_t lock; /* state and operations lock */
|
||||||
|
|
||||||
unsigned long lookup_jif; /* time at which lookup started */
|
unsigned long lookup_jif; /* time at which lookup started */
|
||||||
|
unsigned long oob_event_mask; /* OOB events this object is interested in */
|
||||||
unsigned long event_mask; /* events this object is interested in */
|
unsigned long event_mask; /* events this object is interested in */
|
||||||
unsigned long events; /* events to be processed by this object
|
unsigned long events; /* events to be processed by this object
|
||||||
* (order is important - using fls) */
|
* (order is important - using fls) */
|
||||||
@ -398,6 +392,10 @@ struct fscache_object {
|
|||||||
#define FSCACHE_OBJECT_LOCK 0 /* T if object is busy being processed */
|
#define FSCACHE_OBJECT_LOCK 0 /* T if object is busy being processed */
|
||||||
#define FSCACHE_OBJECT_PENDING_WRITE 1 /* T if object has pending write */
|
#define FSCACHE_OBJECT_PENDING_WRITE 1 /* T if object has pending write */
|
||||||
#define FSCACHE_OBJECT_WAITING 2 /* T if object is waiting on its parent */
|
#define FSCACHE_OBJECT_WAITING 2 /* T if object is waiting on its parent */
|
||||||
|
#define FSCACHE_OBJECT_RETIRE 3 /* T if object should be retired */
|
||||||
|
#define FSCACHE_OBJECT_IS_LIVE 4 /* T if object is not withdrawn or relinquished */
|
||||||
|
#define FSCACHE_OBJECT_IS_LOOKED_UP 5 /* T if object has been looked up */
|
||||||
|
#define FSCACHE_OBJECT_IS_AVAILABLE 6 /* T if object has become active */
|
||||||
|
|
||||||
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 */
|
||||||
@ -415,8 +413,6 @@ struct fscache_object {
|
|||||||
loff_t store_limit_l; /* current storage limit */
|
loff_t store_limit_l; /* current storage limit */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const char *fscache_object_states[];
|
|
||||||
|
|
||||||
extern void fscache_object_init(struct fscache_object *, struct fscache_cookie *,
|
extern void fscache_object_init(struct fscache_object *, struct fscache_cookie *,
|
||||||
struct fscache_cache *);
|
struct fscache_cache *);
|
||||||
|
|
||||||
@ -431,7 +427,7 @@ extern void fscache_object_destroy(struct fscache_object *object);
|
|||||||
|
|
||||||
static inline bool fscache_object_is_live(struct fscache_object *object)
|
static inline bool fscache_object_is_live(struct fscache_object *object)
|
||||||
{
|
{
|
||||||
return object->state < FSCACHE_OBJECT_DYING;
|
return test_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool fscache_object_is_dying(struct fscache_object *object)
|
static inline bool fscache_object_is_dying(struct fscache_object *object)
|
||||||
@ -441,7 +437,7 @@ static inline bool fscache_object_is_dying(struct fscache_object *object)
|
|||||||
|
|
||||||
static inline bool fscache_object_is_available(struct fscache_object *object)
|
static inline bool fscache_object_is_available(struct fscache_object *object)
|
||||||
{
|
{
|
||||||
return object->state >= FSCACHE_OBJECT_AVAILABLE;
|
return test_bit(FSCACHE_OBJECT_IS_AVAILABLE, &object->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool fscache_object_is_active(struct fscache_object *object)
|
static inline bool fscache_object_is_active(struct fscache_object *object)
|
||||||
|
Loading…
Reference in New Issue
Block a user