aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fscache/operation.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2013-05-10 14:50:26 -0400
committerDavid Howells <dhowells@redhat.com>2013-06-19 09:16:47 -0400
commitcaaef6900befb45689b1d1831ce3c7e7fb5b504f (patch)
tree557fa8f425bd18261bea4950a2d821ffe8051903 /fs/fscache/operation.c
parent493f7bc11457bc1f6fbf25a4b2bdf215ebaf050f (diff)
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>
Diffstat (limited to 'fs/fscache/operation.c')
-rw-r--r--fs/fscache/operation.c22
1 files changed, 9 insertions, 13 deletions
diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c
index ccf02194e7a6..4da211b21ddf 100644
--- a/fs/fscache/operation.c
+++ b/fs/fscache/operation.c
@@ -119,7 +119,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
119 /* need to issue a new write op after this */ 119 /* need to issue a new write op after this */
120 clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags); 120 clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
121 ret = 0; 121 ret = 0;
122 } else if (object->state == FSCACHE_OBJECT_CREATING) { 122 } else if (test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)) {
123 op->object = object; 123 op->object = object;
124 object->n_ops++; 124 object->n_ops++;
125 object->n_exclusive++; /* reads and writes must wait */ 125 object->n_exclusive++; /* reads and writes must wait */
@@ -144,7 +144,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
144 */ 144 */
145static void fscache_report_unexpected_submission(struct fscache_object *object, 145static void fscache_report_unexpected_submission(struct fscache_object *object,
146 struct fscache_operation *op, 146 struct fscache_operation *op,
147 unsigned long ostate) 147 const struct fscache_state *ostate)
148{ 148{
149 static bool once_only; 149 static bool once_only;
150 struct fscache_operation *p; 150 struct fscache_operation *p;
@@ -155,11 +155,8 @@ static void fscache_report_unexpected_submission(struct fscache_object *object,
155 once_only = true; 155 once_only = true;
156 156
157 kdebug("unexpected submission OP%x [OBJ%x %s]", 157 kdebug("unexpected submission OP%x [OBJ%x %s]",
158 op->debug_id, object->debug_id, 158 op->debug_id, object->debug_id, object->state->name);
159 fscache_object_states[object->state]); 159 kdebug("objstate=%s [%s]", object->state->name, ostate->name);
160 kdebug("objstate=%s [%s]",
161 fscache_object_states[object->state],
162 fscache_object_states[ostate]);
163 kdebug("objflags=%lx", object->flags); 160 kdebug("objflags=%lx", object->flags);
164 kdebug("objevent=%lx [%lx]", object->events, object->event_mask); 161 kdebug("objevent=%lx [%lx]", object->events, object->event_mask);
165 kdebug("ops=%u inp=%u exc=%u", 162 kdebug("ops=%u inp=%u exc=%u",
@@ -190,7 +187,7 @@ static void fscache_report_unexpected_submission(struct fscache_object *object,
190int fscache_submit_op(struct fscache_object *object, 187int fscache_submit_op(struct fscache_object *object,
191 struct fscache_operation *op) 188 struct fscache_operation *op)
192{ 189{
193 unsigned long ostate; 190 const struct fscache_state *ostate;
194 int ret; 191 int ret;
195 192
196 _enter("{OBJ%x OP%x},{%u}", 193 _enter("{OBJ%x OP%x},{%u}",
@@ -226,16 +223,14 @@ int fscache_submit_op(struct fscache_object *object,
226 fscache_run_op(object, op); 223 fscache_run_op(object, op);
227 } 224 }
228 ret = 0; 225 ret = 0;
229 } else if (object->state == FSCACHE_OBJECT_CREATING) { 226 } else if (test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)) {
230 op->object = object; 227 op->object = object;
231 object->n_ops++; 228 object->n_ops++;
232 atomic_inc(&op->usage); 229 atomic_inc(&op->usage);
233 list_add_tail(&op->pend_link, &object->pending_ops); 230 list_add_tail(&op->pend_link, &object->pending_ops);
234 fscache_stat(&fscache_n_op_pend); 231 fscache_stat(&fscache_n_op_pend);
235 ret = 0; 232 ret = 0;
236 } else if (object->state == FSCACHE_OBJECT_DYING || 233 } else if (fscache_object_is_dying(object)) {
237 object->state == FSCACHE_OBJECT_LC_DYING ||
238 object->state == FSCACHE_OBJECT_WITHDRAWING) {
239 fscache_stat(&fscache_n_op_rejected); 234 fscache_stat(&fscache_n_op_rejected);
240 op->state = FSCACHE_OP_ST_CANCELLED; 235 op->state = FSCACHE_OP_ST_CANCELLED;
241 ret = -ENOBUFS; 236 ret = -ENOBUFS;
@@ -266,13 +261,14 @@ void fscache_abort_object(struct fscache_object *object)
266 261
267/* 262/*
268 * jump start the operation processing on an object 263 * jump start the operation processing on an object
269 * - caller must hold object->lock
270 */ 264 */
271void fscache_start_operations(struct fscache_object *object) 265void fscache_start_operations(struct fscache_object *object)
272{ 266{
273 struct fscache_operation *op; 267 struct fscache_operation *op;
274 bool stop = false; 268 bool stop = false;
275 269
270 ASSERT(spin_is_locked(&object->lock));
271
276 while (!list_empty(&object->pending_ops) && !stop) { 272 while (!list_empty(&object->pending_ops) && !stop) {
277 op = list_entry(object->pending_ops.next, 273 op = list_entry(object->pending_ops.next,
278 struct fscache_operation, pend_link); 274 struct fscache_operation, pend_link);