aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fscache/operation.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fscache/operation.c')
-rw-r--r--fs/fscache/operation.c91
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);
64static void fscache_run_op(struct fscache_object *object, 65static 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,
80int fscache_submit_exclusive_op(struct fscache_object *object, 84int 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 */
329void 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}
355EXPORT_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