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.c140
1 files changed, 108 insertions, 32 deletions
diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c
index 30afdfa7aec7..762a9ec4ffa4 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);
@@ -84,18 +88,21 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
84 88
85 _enter("{OBJ%x OP%x},", object->debug_id, op->debug_id); 89 _enter("{OBJ%x OP%x},", object->debug_id, op->debug_id);
86 90
91 ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED);
92 ASSERTCMP(atomic_read(&op->usage), >, 0);
93
87 spin_lock(&object->lock); 94 spin_lock(&object->lock);
88 ASSERTCMP(object->n_ops, >=, object->n_in_progress); 95 ASSERTCMP(object->n_ops, >=, object->n_in_progress);
89 ASSERTCMP(object->n_ops, >=, object->n_exclusive); 96 ASSERTCMP(object->n_ops, >=, object->n_exclusive);
90 ASSERT(list_empty(&op->pend_link)); 97 ASSERT(list_empty(&op->pend_link));
91 98
92 ret = -ENOBUFS; 99 op->state = FSCACHE_OP_ST_PENDING;
93 if (fscache_object_is_active(object)) { 100 if (fscache_object_is_active(object)) {
94 op->object = object; 101 op->object = object;
95 object->n_ops++; 102 object->n_ops++;
96 object->n_exclusive++; /* reads and writes must wait */ 103 object->n_exclusive++; /* reads and writes must wait */
97 104
98 if (object->n_ops > 1) { 105 if (object->n_in_progress > 0) {
99 atomic_inc(&op->usage); 106 atomic_inc(&op->usage);
100 list_add_tail(&op->pend_link, &object->pending_ops); 107 list_add_tail(&op->pend_link, &object->pending_ops);
101 fscache_stat(&fscache_n_op_pend); 108 fscache_stat(&fscache_n_op_pend);
@@ -121,8 +128,11 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
121 fscache_stat(&fscache_n_op_pend); 128 fscache_stat(&fscache_n_op_pend);
122 ret = 0; 129 ret = 0;
123 } else { 130 } else {
124 /* not allowed to submit ops in any other state */ 131 /* If we're in any other state, there must have been an I/O
125 BUG(); 132 * error of some nature.
133 */
134 ASSERT(test_bit(FSCACHE_IOERROR, &object->cache->flags));
135 ret = -EIO;
126 } 136 }
127 137
128 spin_unlock(&object->lock); 138 spin_unlock(&object->lock);
@@ -186,6 +196,7 @@ int fscache_submit_op(struct fscache_object *object,
186 _enter("{OBJ%x OP%x},{%u}", 196 _enter("{OBJ%x OP%x},{%u}",
187 object->debug_id, op->debug_id, atomic_read(&op->usage)); 197 object->debug_id, op->debug_id, atomic_read(&op->usage));
188 198
199 ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED);
189 ASSERTCMP(atomic_read(&op->usage), >, 0); 200 ASSERTCMP(atomic_read(&op->usage), >, 0);
190 201
191 spin_lock(&object->lock); 202 spin_lock(&object->lock);
@@ -196,6 +207,7 @@ int fscache_submit_op(struct fscache_object *object,
196 ostate = object->state; 207 ostate = object->state;
197 smp_rmb(); 208 smp_rmb();
198 209
210 op->state = FSCACHE_OP_ST_PENDING;
199 if (fscache_object_is_active(object)) { 211 if (fscache_object_is_active(object)) {
200 op->object = object; 212 op->object = object;
201 object->n_ops++; 213 object->n_ops++;
@@ -225,12 +237,15 @@ int fscache_submit_op(struct fscache_object *object,
225 object->state == FSCACHE_OBJECT_LC_DYING || 237 object->state == FSCACHE_OBJECT_LC_DYING ||
226 object->state == FSCACHE_OBJECT_WITHDRAWING) { 238 object->state == FSCACHE_OBJECT_WITHDRAWING) {
227 fscache_stat(&fscache_n_op_rejected); 239 fscache_stat(&fscache_n_op_rejected);
240 op->state = FSCACHE_OP_ST_CANCELLED;
228 ret = -ENOBUFS; 241 ret = -ENOBUFS;
229 } else if (!test_bit(FSCACHE_IOERROR, &object->cache->flags)) { 242 } else if (!test_bit(FSCACHE_IOERROR, &object->cache->flags)) {
230 fscache_report_unexpected_submission(object, op, ostate); 243 fscache_report_unexpected_submission(object, op, ostate);
231 ASSERT(!fscache_object_is_active(object)); 244 ASSERT(!fscache_object_is_active(object));
245 op->state = FSCACHE_OP_ST_CANCELLED;
232 ret = -ENOBUFS; 246 ret = -ENOBUFS;
233 } else { 247 } else {
248 op->state = FSCACHE_OP_ST_CANCELLED;
234 ret = -ENOBUFS; 249 ret = -ENOBUFS;
235 } 250 }
236 251
@@ -283,20 +298,28 @@ void fscache_start_operations(struct fscache_object *object)
283/* 298/*
284 * cancel an operation that's pending on an object 299 * cancel an operation that's pending on an object
285 */ 300 */
286int fscache_cancel_op(struct fscache_operation *op) 301int fscache_cancel_op(struct fscache_operation *op,
302 void (*do_cancel)(struct fscache_operation *))
287{ 303{
288 struct fscache_object *object = op->object; 304 struct fscache_object *object = op->object;
289 int ret; 305 int ret;
290 306
291 _enter("OBJ%x OP%x}", op->object->debug_id, op->debug_id); 307 _enter("OBJ%x OP%x}", op->object->debug_id, op->debug_id);
292 308
309 ASSERTCMP(op->state, >=, FSCACHE_OP_ST_PENDING);
310 ASSERTCMP(op->state, !=, FSCACHE_OP_ST_CANCELLED);
311 ASSERTCMP(atomic_read(&op->usage), >, 0);
312
293 spin_lock(&object->lock); 313 spin_lock(&object->lock);
294 314
295 ret = -EBUSY; 315 ret = -EBUSY;
296 if (!list_empty(&op->pend_link)) { 316 if (op->state == FSCACHE_OP_ST_PENDING) {
317 ASSERT(!list_empty(&op->pend_link));
297 fscache_stat(&fscache_n_op_cancelled); 318 fscache_stat(&fscache_n_op_cancelled);
298 list_del_init(&op->pend_link); 319 list_del_init(&op->pend_link);
299 object->n_ops--; 320 if (do_cancel)
321 do_cancel(op);
322 op->state = FSCACHE_OP_ST_CANCELLED;
300 if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) 323 if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))
301 object->n_exclusive--; 324 object->n_exclusive--;
302 if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags)) 325 if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags))
@@ -311,6 +334,70 @@ int fscache_cancel_op(struct fscache_operation *op)
311} 334}
312 335
313/* 336/*
337 * Cancel all pending operations on an object
338 */
339void fscache_cancel_all_ops(struct fscache_object *object)
340{
341 struct fscache_operation *op;
342
343 _enter("OBJ%x", object->debug_id);
344
345 spin_lock(&object->lock);
346
347 while (!list_empty(&object->pending_ops)) {
348 op = list_entry(object->pending_ops.next,
349 struct fscache_operation, pend_link);
350 fscache_stat(&fscache_n_op_cancelled);
351 list_del_init(&op->pend_link);
352
353 ASSERTCMP(op->state, ==, FSCACHE_OP_ST_PENDING);
354 op->state = FSCACHE_OP_ST_CANCELLED;
355
356 if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))
357 object->n_exclusive--;
358 if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags))
359 wake_up_bit(&op->flags, FSCACHE_OP_WAITING);
360 fscache_put_operation(op);
361 cond_resched_lock(&object->lock);
362 }
363
364 spin_unlock(&object->lock);
365 _leave("");
366}
367
368/*
369 * Record the completion or cancellation of an in-progress operation.
370 */
371void fscache_op_complete(struct fscache_operation *op, bool cancelled)
372{
373 struct fscache_object *object = op->object;
374
375 _enter("OBJ%x", object->debug_id);
376
377 ASSERTCMP(op->state, ==, FSCACHE_OP_ST_IN_PROGRESS);
378 ASSERTCMP(object->n_in_progress, >, 0);
379 ASSERTIFCMP(test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags),
380 object->n_exclusive, >, 0);
381 ASSERTIFCMP(test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags),
382 object->n_in_progress, ==, 1);
383
384 spin_lock(&object->lock);
385
386 op->state = cancelled ?
387 FSCACHE_OP_ST_CANCELLED : FSCACHE_OP_ST_COMPLETE;
388
389 if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))
390 object->n_exclusive--;
391 object->n_in_progress--;
392 if (object->n_in_progress == 0)
393 fscache_start_operations(object);
394
395 spin_unlock(&object->lock);
396 _leave("");
397}
398EXPORT_SYMBOL(fscache_op_complete);
399
400/*
314 * release an operation 401 * release an operation
315 * - queues pending ops if this is the last in-progress op 402 * - queues pending ops if this is the last in-progress op
316 */ 403 */
@@ -328,8 +415,9 @@ void fscache_put_operation(struct fscache_operation *op)
328 return; 415 return;
329 416
330 _debug("PUT OP"); 417 _debug("PUT OP");
331 if (test_and_set_bit(FSCACHE_OP_DEAD, &op->flags)) 418 ASSERTIFCMP(op->state != FSCACHE_OP_ST_COMPLETE,
332 BUG(); 419 op->state, ==, FSCACHE_OP_ST_CANCELLED);
420 op->state = FSCACHE_OP_ST_DEAD;
333 421
334 fscache_stat(&fscache_n_op_release); 422 fscache_stat(&fscache_n_op_release);
335 423
@@ -340,8 +428,14 @@ void fscache_put_operation(struct fscache_operation *op)
340 428
341 object = op->object; 429 object = op->object;
342 430
343 if (test_bit(FSCACHE_OP_DEC_READ_CNT, &op->flags)) 431 if (test_bit(FSCACHE_OP_DEC_READ_CNT, &op->flags)) {
344 atomic_dec(&object->n_reads); 432 if (atomic_dec_and_test(&object->n_reads)) {
433 clear_bit(FSCACHE_COOKIE_WAITING_ON_READS,
434 &object->cookie->flags);
435 wake_up_bit(&object->cookie->flags,
436 FSCACHE_COOKIE_WAITING_ON_READS);
437 }
438 }
345 439
346 /* now... we may get called with the object spinlock held, so we 440 /* now... we may get called with the object spinlock held, so we
347 * complete the cleanup here only if we can immediately acquire the 441 * complete the cleanup here only if we can immediately acquire the
@@ -359,16 +453,6 @@ void fscache_put_operation(struct fscache_operation *op)
359 return; 453 return;
360 } 454 }
361 455
362 if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) {
363 ASSERTCMP(object->n_exclusive, >, 0);
364 object->n_exclusive--;
365 }
366
367 ASSERTCMP(object->n_in_progress, >, 0);
368 object->n_in_progress--;
369 if (object->n_in_progress == 0)
370 fscache_start_operations(object);
371
372 ASSERTCMP(object->n_ops, >, 0); 456 ASSERTCMP(object->n_ops, >, 0);
373 object->n_ops--; 457 object->n_ops--;
374 if (object->n_ops == 0) 458 if (object->n_ops == 0)
@@ -407,23 +491,14 @@ void fscache_operation_gc(struct work_struct *work)
407 spin_unlock(&cache->op_gc_list_lock); 491 spin_unlock(&cache->op_gc_list_lock);
408 492
409 object = op->object; 493 object = op->object;
494 spin_lock(&object->lock);
410 495
411 _debug("GC DEFERRED REL OBJ%x OP%x", 496 _debug("GC DEFERRED REL OBJ%x OP%x",
412 object->debug_id, op->debug_id); 497 object->debug_id, op->debug_id);
413 fscache_stat(&fscache_n_op_gc); 498 fscache_stat(&fscache_n_op_gc);
414 499
415 ASSERTCMP(atomic_read(&op->usage), ==, 0); 500 ASSERTCMP(atomic_read(&op->usage), ==, 0);
416 501 ASSERTCMP(op->state, ==, FSCACHE_OP_ST_DEAD);
417 spin_lock(&object->lock);
418 if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags)) {
419 ASSERTCMP(object->n_exclusive, >, 0);
420 object->n_exclusive--;
421 }
422
423 ASSERTCMP(object->n_in_progress, >, 0);
424 object->n_in_progress--;
425 if (object->n_in_progress == 0)
426 fscache_start_operations(object);
427 502
428 ASSERTCMP(object->n_ops, >, 0); 503 ASSERTCMP(object->n_ops, >, 0);
429 object->n_ops--; 504 object->n_ops--;
@@ -431,6 +506,7 @@ void fscache_operation_gc(struct work_struct *work)
431 fscache_raise_event(object, FSCACHE_OBJECT_EV_CLEARED); 506 fscache_raise_event(object, FSCACHE_OBJECT_EV_CLEARED);
432 507
433 spin_unlock(&object->lock); 508 spin_unlock(&object->lock);
509 kfree(op);
434 510
435 } while (count++ < 20); 511 } while (count++ < 20);
436 512