diff options
Diffstat (limited to 'fs/fscache/operation.c')
-rw-r--r-- | fs/fscache/operation.c | 82 |
1 files changed, 54 insertions, 28 deletions
diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c index 09e43b6e822f..296492efb81b 100644 --- a/fs/fscache/operation.c +++ b/fs/fscache/operation.c | |||
@@ -34,32 +34,31 @@ void fscache_enqueue_operation(struct fscache_operation *op) | |||
34 | 34 | ||
35 | fscache_set_op_state(op, "EnQ"); | 35 | fscache_set_op_state(op, "EnQ"); |
36 | 36 | ||
37 | ASSERT(list_empty(&op->pend_link)); | ||
37 | ASSERT(op->processor != NULL); | 38 | ASSERT(op->processor != NULL); |
38 | ASSERTCMP(op->object->state, >=, FSCACHE_OBJECT_AVAILABLE); | 39 | ASSERTCMP(op->object->state, >=, FSCACHE_OBJECT_AVAILABLE); |
39 | ASSERTCMP(atomic_read(&op->usage), >, 0); | 40 | ASSERTCMP(atomic_read(&op->usage), >, 0); |
40 | 41 | ||
41 | if (list_empty(&op->pend_link)) { | 42 | fscache_stat(&fscache_n_op_enqueue); |
42 | switch (op->flags & FSCACHE_OP_TYPE) { | 43 | switch (op->flags & FSCACHE_OP_TYPE) { |
43 | case FSCACHE_OP_FAST: | 44 | case FSCACHE_OP_FAST: |
44 | _debug("queue fast"); | 45 | _debug("queue fast"); |
45 | atomic_inc(&op->usage); | 46 | atomic_inc(&op->usage); |
46 | if (!schedule_work(&op->fast_work)) | 47 | if (!schedule_work(&op->fast_work)) |
47 | fscache_put_operation(op); | 48 | fscache_put_operation(op); |
48 | break; | 49 | break; |
49 | case FSCACHE_OP_SLOW: | 50 | case FSCACHE_OP_SLOW: |
50 | _debug("queue slow"); | 51 | _debug("queue slow"); |
51 | slow_work_enqueue(&op->slow_work); | 52 | slow_work_enqueue(&op->slow_work); |
52 | break; | 53 | break; |
53 | case FSCACHE_OP_MYTHREAD: | 54 | case FSCACHE_OP_MYTHREAD: |
54 | _debug("queue for caller's attention"); | 55 | _debug("queue for caller's attention"); |
55 | break; | 56 | break; |
56 | default: | 57 | default: |
57 | printk(KERN_ERR "FS-Cache: Unexpected op type %lx", | 58 | printk(KERN_ERR "FS-Cache: Unexpected op type %lx", |
58 | op->flags); | 59 | op->flags); |
59 | BUG(); | 60 | BUG(); |
60 | break; | 61 | break; |
61 | } | ||
62 | fscache_stat(&fscache_n_op_enqueue); | ||
63 | } | 62 | } |
64 | } | 63 | } |
65 | EXPORT_SYMBOL(fscache_enqueue_operation); | 64 | EXPORT_SYMBOL(fscache_enqueue_operation); |
@@ -97,6 +96,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object, | |||
97 | spin_lock(&object->lock); | 96 | spin_lock(&object->lock); |
98 | ASSERTCMP(object->n_ops, >=, object->n_in_progress); | 97 | ASSERTCMP(object->n_ops, >=, object->n_in_progress); |
99 | ASSERTCMP(object->n_ops, >=, object->n_exclusive); | 98 | ASSERTCMP(object->n_ops, >=, object->n_exclusive); |
99 | ASSERT(list_empty(&op->pend_link)); | ||
100 | 100 | ||
101 | ret = -ENOBUFS; | 101 | ret = -ENOBUFS; |
102 | if (fscache_object_is_active(object)) { | 102 | if (fscache_object_is_active(object)) { |
@@ -202,6 +202,7 @@ int fscache_submit_op(struct fscache_object *object, | |||
202 | spin_lock(&object->lock); | 202 | spin_lock(&object->lock); |
203 | ASSERTCMP(object->n_ops, >=, object->n_in_progress); | 203 | ASSERTCMP(object->n_ops, >=, object->n_in_progress); |
204 | ASSERTCMP(object->n_ops, >=, object->n_exclusive); | 204 | ASSERTCMP(object->n_ops, >=, object->n_exclusive); |
205 | ASSERT(list_empty(&op->pend_link)); | ||
205 | 206 | ||
206 | ostate = object->state; | 207 | ostate = object->state; |
207 | smp_rmb(); | 208 | smp_rmb(); |
@@ -273,12 +274,7 @@ void fscache_start_operations(struct fscache_object *object) | |||
273 | stop = true; | 274 | stop = true; |
274 | } | 275 | } |
275 | list_del_init(&op->pend_link); | 276 | list_del_init(&op->pend_link); |
276 | object->n_in_progress++; | 277 | fscache_run_op(object, op); |
277 | |||
278 | if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags)) | ||
279 | wake_up_bit(&op->flags, FSCACHE_OP_WAITING); | ||
280 | if (op->processor) | ||
281 | fscache_enqueue_operation(op); | ||
282 | 278 | ||
283 | /* the pending queue was holding a ref on the object */ | 279 | /* the pending queue was holding a ref on the object */ |
284 | fscache_put_operation(op); | 280 | fscache_put_operation(op); |
@@ -291,6 +287,36 @@ void fscache_start_operations(struct fscache_object *object) | |||
291 | } | 287 | } |
292 | 288 | ||
293 | /* | 289 | /* |
290 | * cancel an operation that's pending on an object | ||
291 | */ | ||
292 | int fscache_cancel_op(struct fscache_operation *op) | ||
293 | { | ||
294 | struct fscache_object *object = op->object; | ||
295 | int ret; | ||
296 | |||
297 | _enter("OBJ%x OP%x}", op->object->debug_id, op->debug_id); | ||
298 | |||
299 | spin_lock(&object->lock); | ||
300 | |||
301 | ret = -EBUSY; | ||
302 | if (!list_empty(&op->pend_link)) { | ||
303 | fscache_stat(&fscache_n_op_cancelled); | ||
304 | list_del_init(&op->pend_link); | ||
305 | object->n_ops--; | ||
306 | if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) | ||
307 | object->n_exclusive--; | ||
308 | if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags)) | ||
309 | wake_up_bit(&op->flags, FSCACHE_OP_WAITING); | ||
310 | fscache_put_operation(op); | ||
311 | ret = 0; | ||
312 | } | ||
313 | |||
314 | spin_unlock(&object->lock); | ||
315 | _leave(" = %d", ret); | ||
316 | return ret; | ||
317 | } | ||
318 | |||
319 | /* | ||
294 | * release an operation | 320 | * release an operation |
295 | * - queues pending ops if this is the last in-progress op | 321 | * - queues pending ops if this is the last in-progress op |
296 | */ | 322 | */ |