/** * fscache_enqueue_operation - Enqueue an operation for processing * @op: The operation to enqueue * * Enqueue an operation for processing by the FS-Cache thread pool. * * This will get its own ref on the object. */ void fscache_enqueue_operation(struct fscache_operation *op) { _enter("{OBJ%x OP%x,%u}", op->object->debug_id, op->debug_id, atomic_read(&op->usage)); fscache_set_op_state(op, "EnQ"); ASSERT(list_empty(&op->pend_link)); ASSERT(op->processor != NULL); ASSERT(fscache_object_is_available(op->object)); ASSERTCMP(atomic_read(&op->usage), >, 0); ASSERTCMP(op->state, ==, FSCACHE_OP_ST_IN_PROGRESS); fscache_stat(&fscache_n_op_enqueue); switch (op->flags & FSCACHE_OP_TYPE) { case FSCACHE_OP_FAST: _debug("queue fast"); atomic_inc(&op->usage); if (!schedule_work(&op->fast_work)) fscache_put_operation(op); break; case FSCACHE_OP_SLOW: _debug("queue slow"); slow_work_enqueue(&op->slow_work); break; case FSCACHE_OP_MYTHREAD: _debug("queue for caller's attention"); break; default: printk(KERN_ERR "FS-Cache: Unexpected op type %lx", op->flags); BUG(); break; } }
/** * fscache_enqueue_operation - Enqueue an operation for processing * @op: The operation to enqueue * * Enqueue an operation for processing by the FS-Cache thread pool. * * This will get its own ref on the object. */ void fscache_enqueue_operation(struct fscache_operation *op) { _enter("{OBJ%x OP%x,%u}", op->object->debug_id, op->debug_id, atomic_read(&op->usage)); ASSERT(list_empty(&op->pend_link)); ASSERT(op->processor != NULL); ASSERT(fscache_object_is_available(op->object)); ASSERTCMP(atomic_read(&op->usage), >, 0); ASSERTCMP(op->state, ==, FSCACHE_OP_ST_IN_PROGRESS); fscache_stat(&fscache_n_op_enqueue); switch (op->flags & FSCACHE_OP_TYPE) { case FSCACHE_OP_ASYNC: _debug("queue async"); atomic_inc(&op->usage); if (!queue_work(fscache_op_wq, &op->work)) fscache_put_operation(op); break; case FSCACHE_OP_MYTHREAD: _debug("queue for caller's attention"); break; default: pr_err("Unexpected op type %lx", op->flags); BUG(); break; } }
/* * look an object up in the cache from which it was allocated * - we hold an "access lock" on the parent object, so the parent object cannot * be withdrawn by either party till we've finished */ static const struct fscache_state *fscache_look_up_object(struct fscache_object *object, int event) { struct fscache_cookie *cookie = object->cookie; struct fscache_object *parent = object->parent; int ret; _enter("{OBJ%x},%d", object->debug_id, event); object->oob_table = fscache_osm_lookup_oob; ASSERT(parent != NULL); ASSERTCMP(parent->n_ops, >, 0); ASSERTCMP(parent->n_obj_ops, >, 0); /* make sure the parent is still available */ ASSERT(fscache_object_is_available(parent)); if (fscache_object_is_dying(parent) || test_bit(FSCACHE_IOERROR, &object->cache->flags) || !fscache_use_cookie(object)) { _leave(" [unavailable]"); return transit_to(LOOKUP_FAILURE); } _debug("LOOKUP \"%s\" in \"%s\"", cookie->def->name, object->cache->tag->name); fscache_stat(&fscache_n_object_lookups); fscache_stat(&fscache_n_cop_lookup_object); ret = object->cache->ops->lookup_object(object); fscache_stat_d(&fscache_n_cop_lookup_object); fscache_unuse_cookie(object); if (ret == -ETIMEDOUT) { /* probably stuck behind another object, so move this one to * the back of the queue */ fscache_stat(&fscache_n_object_lookups_timed_out); _leave(" [timeout]"); return NO_TRANSIT; } if (ret < 0) { _leave(" [error]"); return transit_to(LOOKUP_FAILURE); } _leave(" [ok]"); return transit_to(OBJECT_AVAILABLE); }
/* * initialise an object * - check the specified object's parent to see if we can make use of it * immediately to do a creation * - we may need to start the process of creating a parent and we need to wait * for the parent's lookup and creation to complete if it's not there yet */ static const struct fscache_state *fscache_initialise_object(struct fscache_object *object, int event) { struct fscache_object *parent; bool success; _enter("{OBJ%x},%d", object->debug_id, event); ASSERT(list_empty(&object->dep_link)); parent = object->parent; if (!parent) { _leave(" [no parent]"); return transit_to(DROP_OBJECT); } _debug("parent: %s of:%lx", parent->state->name, parent->flags); if (fscache_object_is_dying(parent)) { _leave(" [bad parent]"); return transit_to(DROP_OBJECT); } if (fscache_object_is_available(parent)) { _leave(" [ready]"); return transit_to(PARENT_READY); } _debug("wait"); spin_lock(&parent->lock); fscache_stat(&fscache_n_cop_grab_object); success = false; if (fscache_object_is_live(parent) && object->cache->ops->grab_object(object)) { list_add(&object->dep_link, &parent->dependents); success = true; } fscache_stat_d(&fscache_n_cop_grab_object); spin_unlock(&parent->lock); if (!success) { _leave(" [grab failed]"); return transit_to(DROP_OBJECT); } /* fscache_acquire_non_index_cookie() uses this * to wake the chain up */ fscache_raise_event(parent, FSCACHE_OBJECT_EV_NEW_CHILD); _leave(" [wait]"); return transit_to(WAIT_FOR_PARENT); }