diff options
Diffstat (limited to 'fs/fscache/operation.c')
-rw-r--r-- | fs/fscache/operation.c | 91 |
1 files changed, 59 insertions, 32 deletions
diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c index c857ab824d6e..748f9553c2cb 100644 --- a/fs/fscache/operation.c +++ b/fs/fscache/operation.c | |||
@@ -37,6 +37,7 @@ void fscache_enqueue_operation(struct fscache_operation *op) | |||
37 | ASSERT(op->processor != NULL); | 37 | ASSERT(op->processor != NULL); |
38 | ASSERTCMP(op->object->state, >=, FSCACHE_OBJECT_AVAILABLE); | 38 | ASSERTCMP(op->object->state, >=, FSCACHE_OBJECT_AVAILABLE); |
39 | ASSERTCMP(atomic_read(&op->usage), >, 0); | 39 | ASSERTCMP(atomic_read(&op->usage), >, 0); |
40 | ASSERTCMP(op->state, ==, FSCACHE_OP_ST_IN_PROGRESS); | ||
40 | 41 | ||
41 | fscache_stat(&fscache_n_op_enqueue); | 42 | fscache_stat(&fscache_n_op_enqueue); |
42 | switch (op->flags & FSCACHE_OP_TYPE) { | 43 | switch (op->flags & FSCACHE_OP_TYPE) { |
@@ -64,6 +65,9 @@ EXPORT_SYMBOL(fscache_enqueue_operation); | |||
64 | static void fscache_run_op(struct fscache_object *object, | 65 | static void fscache_run_op(struct fscache_object *object, |
65 | struct fscache_operation *op) | 66 | struct fscache_operation *op) |
66 | { | 67 | { |
68 | ASSERTCMP(op->state, ==, FSCACHE_OP_ST_PENDING); | ||
69 | |||
70 | op->state = FSCACHE_OP_ST_IN_PROGRESS; | ||
67 | object->n_in_progress++; | 71 | object->n_in_progress++; |
68 | if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags)) | 72 | if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags)) |
69 | wake_up_bit(&op->flags, FSCACHE_OP_WAITING); | 73 | wake_up_bit(&op->flags, FSCACHE_OP_WAITING); |
@@ -80,22 +84,23 @@ static void fscache_run_op(struct fscache_object *object, | |||
80 | int fscache_submit_exclusive_op(struct fscache_object *object, | 84 | int fscache_submit_exclusive_op(struct fscache_object *object, |
81 | struct fscache_operation *op) | 85 | struct fscache_operation *op) |
82 | { | 86 | { |
83 | int ret; | ||
84 | |||
85 | _enter("{OBJ%x OP%x},", object->debug_id, op->debug_id); | 87 | _enter("{OBJ%x OP%x},", object->debug_id, op->debug_id); |
86 | 88 | ||
89 | ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED); | ||
90 | ASSERTCMP(atomic_read(&op->usage), >, 0); | ||
91 | |||
87 | spin_lock(&object->lock); | 92 | spin_lock(&object->lock); |
88 | ASSERTCMP(object->n_ops, >=, object->n_in_progress); | 93 | ASSERTCMP(object->n_ops, >=, object->n_in_progress); |
89 | ASSERTCMP(object->n_ops, >=, object->n_exclusive); | 94 | ASSERTCMP(object->n_ops, >=, object->n_exclusive); |
90 | ASSERT(list_empty(&op->pend_link)); | 95 | ASSERT(list_empty(&op->pend_link)); |
91 | 96 | ||
92 | ret = -ENOBUFS; | 97 | op->state = FSCACHE_OP_ST_PENDING; |
93 | if (fscache_object_is_active(object)) { | 98 | if (fscache_object_is_active(object)) { |
94 | op->object = object; | 99 | op->object = object; |
95 | object->n_ops++; | 100 | object->n_ops++; |
96 | object->n_exclusive++; /* reads and writes must wait */ | 101 | object->n_exclusive++; /* reads and writes must wait */ |
97 | 102 | ||
98 | if (object->n_ops > 1) { | 103 | if (object->n_in_progress > 0) { |
99 | atomic_inc(&op->usage); | 104 | atomic_inc(&op->usage); |
100 | list_add_tail(&op->pend_link, &object->pending_ops); | 105 | list_add_tail(&op->pend_link, &object->pending_ops); |
101 | fscache_stat(&fscache_n_op_pend); | 106 | fscache_stat(&fscache_n_op_pend); |
@@ -111,7 +116,6 @@ int fscache_submit_exclusive_op(struct fscache_object *object, | |||
111 | 116 | ||
112 | /* need to issue a new write op after this */ | 117 | /* need to issue a new write op after this */ |
113 | clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags); | 118 | clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags); |
114 | ret = 0; | ||
115 | } else if (object->state == FSCACHE_OBJECT_CREATING) { | 119 | } else if (object->state == FSCACHE_OBJECT_CREATING) { |
116 | op->object = object; | 120 | op->object = object; |
117 | object->n_ops++; | 121 | object->n_ops++; |
@@ -119,14 +123,13 @@ int fscache_submit_exclusive_op(struct fscache_object *object, | |||
119 | atomic_inc(&op->usage); | 123 | atomic_inc(&op->usage); |
120 | list_add_tail(&op->pend_link, &object->pending_ops); | 124 | list_add_tail(&op->pend_link, &object->pending_ops); |
121 | fscache_stat(&fscache_n_op_pend); | 125 | fscache_stat(&fscache_n_op_pend); |
122 | ret = 0; | ||
123 | } else { | 126 | } else { |
124 | /* not allowed to submit ops in any other state */ | 127 | /* not allowed to submit ops in any other state */ |
125 | BUG(); | 128 | BUG(); |
126 | } | 129 | } |
127 | 130 | ||
128 | spin_unlock(&object->lock); | 131 | spin_unlock(&object->lock); |
129 | return ret; | 132 | return 0; |
130 | } | 133 | } |
131 | 134 | ||
132 | /* | 135 | /* |
@@ -186,6 +189,7 @@ int fscache_submit_op(struct fscache_object *object, | |||
186 | _enter("{OBJ%x OP%x},{%u}", | 189 | _enter("{OBJ%x OP%x},{%u}", |
187 | object->debug_id, op->debug_id, atomic_read(&op->usage)); | 190 | object->debug_id, op->debug_id, atomic_read(&op->usage)); |
188 | 191 | ||
192 | ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED); | ||
189 | ASSERTCMP(atomic_read(&op->usage), >, 0); | 193 | ASSERTCMP(atomic_read(&op->usage), >, 0); |
190 | 194 | ||
191 | spin_lock(&object->lock); | 195 | spin_lock(&object->lock); |
@@ -196,6 +200,7 @@ int fscache_submit_op(struct fscache_object *object, | |||
196 | ostate = object->state; | 200 | ostate = object->state; |
197 | smp_rmb(); | 201 | smp_rmb(); |
198 | 202 | ||
203 | op->state = FSCACHE_OP_ST_PENDING; | ||
199 | if (fscache_object_is_active(object)) { | 204 | if (fscache_object_is_active(object)) { |
200 | op->object = object; | 205 | op->object = object; |
201 | object->n_ops++; | 206 | object->n_ops++; |
@@ -225,12 +230,15 @@ int fscache_submit_op(struct fscache_object *object, | |||
225 | object->state == FSCACHE_OBJECT_LC_DYING || | 230 | object->state == FSCACHE_OBJECT_LC_DYING || |
226 | object->state == FSCACHE_OBJECT_WITHDRAWING) { | 231 | object->state == FSCACHE_OBJECT_WITHDRAWING) { |
227 | fscache_stat(&fscache_n_op_rejected); | 232 | fscache_stat(&fscache_n_op_rejected); |
233 | op->state = FSCACHE_OP_ST_CANCELLED; | ||
228 | ret = -ENOBUFS; | 234 | ret = -ENOBUFS; |
229 | } else if (!test_bit(FSCACHE_IOERROR, &object->cache->flags)) { | 235 | } else if (!test_bit(FSCACHE_IOERROR, &object->cache->flags)) { |
230 | fscache_report_unexpected_submission(object, op, ostate); | 236 | fscache_report_unexpected_submission(object, op, ostate); |
231 | ASSERT(!fscache_object_is_active(object)); | 237 | ASSERT(!fscache_object_is_active(object)); |
238 | op->state = FSCACHE_OP_ST_CANCELLED; | ||
232 | ret = -ENOBUFS; | 239 | ret = -ENOBUFS; |
233 | } else { | 240 | } else { |
241 | op->state = FSCACHE_OP_ST_CANCELLED; | ||
234 | ret = -ENOBUFS; | 242 | ret = -ENOBUFS; |
235 | } | 243 | } |
236 | 244 | ||
@@ -290,13 +298,18 @@ int fscache_cancel_op(struct fscache_operation *op) | |||
290 | 298 | ||
291 | _enter("OBJ%x OP%x}", op->object->debug_id, op->debug_id); | 299 | _enter("OBJ%x OP%x}", op->object->debug_id, op->debug_id); |
292 | 300 | ||
301 | ASSERTCMP(op->state, >=, FSCACHE_OP_ST_PENDING); | ||
302 | ASSERTCMP(op->state, !=, FSCACHE_OP_ST_CANCELLED); | ||
303 | ASSERTCMP(atomic_read(&op->usage), >, 0); | ||
304 | |||
293 | spin_lock(&object->lock); | 305 | spin_lock(&object->lock); |
294 | 306 | ||
295 | ret = -EBUSY; | 307 | ret = -EBUSY; |
296 | if (!list_empty(&op->pend_link)) { | 308 | if (op->state == FSCACHE_OP_ST_PENDING) { |
309 | ASSERT(!list_empty(&op->pend_link)); | ||
297 | fscache_stat(&fscache_n_op_cancelled); | 310 | fscache_stat(&fscache_n_op_cancelled); |
298 | list_del_init(&op->pend_link); | 311 | list_del_init(&op->pend_link); |
299 | object->n_ops--; | 312 | op->state = FSCACHE_OP_ST_CANCELLED; |
300 | if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) | 313 | if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) |
301 | object->n_exclusive--; | 314 | object->n_exclusive--; |
302 | if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags)) | 315 | if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags)) |
@@ -311,6 +324,37 @@ int fscache_cancel_op(struct fscache_operation *op) | |||
311 | } | 324 | } |
312 | 325 | ||
313 | /* | 326 | /* |
327 | * Record the completion of an in-progress operation. | ||
328 | */ | ||
329 | void fscache_op_complete(struct fscache_operation *op) | ||
330 | { | ||
331 | struct fscache_object *object = op->object; | ||
332 | |||
333 | _enter("OBJ%x", object->debug_id); | ||
334 | |||
335 | ASSERTCMP(op->state, ==, FSCACHE_OP_ST_IN_PROGRESS); | ||
336 | ASSERTCMP(object->n_in_progress, >, 0); | ||
337 | ASSERTIFCMP(test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags), | ||
338 | object->n_exclusive, >, 0); | ||
339 | ASSERTIFCMP(test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags), | ||
340 | object->n_in_progress, ==, 1); | ||
341 | |||
342 | spin_lock(&object->lock); | ||
343 | |||
344 | op->state = FSCACHE_OP_ST_COMPLETE; | ||
345 | |||
346 | if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) | ||
347 | object->n_exclusive--; | ||
348 | object->n_in_progress--; | ||
349 | if (object->n_in_progress == 0) | ||
350 | fscache_start_operations(object); | ||
351 | |||
352 | spin_unlock(&object->lock); | ||
353 | _leave(""); | ||
354 | } | ||
355 | EXPORT_SYMBOL(fscache_op_complete); | ||
356 | |||
357 | /* | ||
314 | * release an operation | 358 | * release an operation |
315 | * - queues pending ops if this is the last in-progress op | 359 | * - queues pending ops if this is the last in-progress op |
316 | */ | 360 | */ |
@@ -328,8 +372,9 @@ void fscache_put_operation(struct fscache_operation *op) | |||
328 | return; | 372 | return; |
329 | 373 | ||
330 | _debug("PUT OP"); | 374 | _debug("PUT OP"); |
331 | if (test_and_set_bit(FSCACHE_OP_DEAD, &op->flags)) | 375 | ASSERTIFCMP(op->state != FSCACHE_OP_ST_COMPLETE, |
332 | BUG(); | 376 | op->state, ==, FSCACHE_OP_ST_CANCELLED); |
377 | op->state = FSCACHE_OP_ST_DEAD; | ||
333 | 378 | ||
334 | fscache_stat(&fscache_n_op_release); | 379 | fscache_stat(&fscache_n_op_release); |
335 | 380 | ||
@@ -365,16 +410,6 @@ void fscache_put_operation(struct fscache_operation *op) | |||
365 | return; | 410 | return; |
366 | } | 411 | } |
367 | 412 | ||
368 | if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) { | ||
369 | ASSERTCMP(object->n_exclusive, >, 0); | ||
370 | object->n_exclusive--; | ||
371 | } | ||
372 | |||
373 | ASSERTCMP(object->n_in_progress, >, 0); | ||
374 | object->n_in_progress--; | ||
375 | if (object->n_in_progress == 0) | ||
376 | fscache_start_operations(object); | ||
377 | |||
378 | ASSERTCMP(object->n_ops, >, 0); | 413 | ASSERTCMP(object->n_ops, >, 0); |
379 | object->n_ops--; | 414 | object->n_ops--; |
380 | if (object->n_ops == 0) | 415 | if (object->n_ops == 0) |
@@ -413,23 +448,14 @@ void fscache_operation_gc(struct work_struct *work) | |||
413 | spin_unlock(&cache->op_gc_list_lock); | 448 | spin_unlock(&cache->op_gc_list_lock); |
414 | 449 | ||
415 | object = op->object; | 450 | object = op->object; |
451 | spin_lock(&object->lock); | ||
416 | 452 | ||
417 | _debug("GC DEFERRED REL OBJ%x OP%x", | 453 | _debug("GC DEFERRED REL OBJ%x OP%x", |
418 | object->debug_id, op->debug_id); | 454 | object->debug_id, op->debug_id); |
419 | fscache_stat(&fscache_n_op_gc); | 455 | fscache_stat(&fscache_n_op_gc); |
420 | 456 | ||
421 | ASSERTCMP(atomic_read(&op->usage), ==, 0); | 457 | ASSERTCMP(atomic_read(&op->usage), ==, 0); |
422 | 458 | ASSERTCMP(op->state, ==, FSCACHE_OP_ST_DEAD); | |
423 | spin_lock(&object->lock); | ||
424 | if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) { | ||
425 | ASSERTCMP(object->n_exclusive, >, 0); | ||
426 | object->n_exclusive--; | ||
427 | } | ||
428 | |||
429 | ASSERTCMP(object->n_in_progress, >, 0); | ||
430 | object->n_in_progress--; | ||
431 | if (object->n_in_progress == 0) | ||
432 | fscache_start_operations(object); | ||
433 | 459 | ||
434 | ASSERTCMP(object->n_ops, >, 0); | 460 | ASSERTCMP(object->n_ops, >, 0); |
435 | object->n_ops--; | 461 | object->n_ops--; |
@@ -437,6 +463,7 @@ void fscache_operation_gc(struct work_struct *work) | |||
437 | fscache_raise_event(object, FSCACHE_OBJECT_EV_CLEARED); | 463 | fscache_raise_event(object, FSCACHE_OBJECT_EV_CLEARED); |
438 | 464 | ||
439 | spin_unlock(&object->lock); | 465 | spin_unlock(&object->lock); |
466 | kfree(op); | ||
440 | 467 | ||
441 | } while (count++ < 20); | 468 | } while (count++ < 20); |
442 | 469 | ||