diff options
-rw-r--r-- | Documentation/filesystems/caching/fscache.txt | 2 | ||||
-rw-r--r-- | fs/fscache/internal.h | 5 | ||||
-rw-r--r-- | fs/fscache/object.c | 1 | ||||
-rw-r--r-- | fs/fscache/page.c | 112 | ||||
-rw-r--r-- | fs/fscache/stats.c | 12 | ||||
-rw-r--r-- | include/linux/fscache-cache.h | 4 |
6 files changed, 75 insertions, 61 deletions
diff --git a/Documentation/filesystems/caching/fscache.txt b/Documentation/filesystems/caching/fscache.txt index 7097fd29fb3d..3c23411956bb 100644 --- a/Documentation/filesystems/caching/fscache.txt +++ b/Documentation/filesystems/caching/fscache.txt | |||
@@ -253,6 +253,7 @@ proc files. | |||
253 | int=N Number of alloc reqs aborted -ERESTARTSYS | 253 | int=N Number of alloc reqs aborted -ERESTARTSYS |
254 | ops=N Number of alloc reqs submitted | 254 | ops=N Number of alloc reqs submitted |
255 | owt=N Number of alloc reqs waited for CPU time | 255 | owt=N Number of alloc reqs waited for CPU time |
256 | abt=N Number of alloc reqs aborted due to object death | ||
256 | Retrvls n=N Number of retrieval (read) requests seen | 257 | Retrvls n=N Number of retrieval (read) requests seen |
257 | ok=N Number of successful retr reqs | 258 | ok=N Number of successful retr reqs |
258 | wt=N Number of retr reqs that waited on lookup completion | 259 | wt=N Number of retr reqs that waited on lookup completion |
@@ -262,6 +263,7 @@ proc files. | |||
262 | oom=N Number of retr reqs failed -ENOMEM | 263 | oom=N Number of retr reqs failed -ENOMEM |
263 | ops=N Number of retr reqs submitted | 264 | ops=N Number of retr reqs submitted |
264 | owt=N Number of retr reqs waited for CPU time | 265 | owt=N Number of retr reqs waited for CPU time |
266 | abt=N Number of retr reqs aborted due to object death | ||
265 | Stores n=N Number of storage (write) requests seen | 267 | Stores n=N Number of storage (write) requests seen |
266 | ok=N Number of successful store reqs | 268 | ok=N Number of successful store reqs |
267 | agn=N Number of store reqs on a page already pending storage | 269 | agn=N Number of store reqs on a page already pending storage |
diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h index 2bf463d26080..5b49a373689b 100644 --- a/fs/fscache/internal.h +++ b/fs/fscache/internal.h | |||
@@ -156,6 +156,7 @@ extern atomic_t fscache_n_allocs_ok; | |||
156 | extern atomic_t fscache_n_allocs_wait; | 156 | extern atomic_t fscache_n_allocs_wait; |
157 | extern atomic_t fscache_n_allocs_nobufs; | 157 | extern atomic_t fscache_n_allocs_nobufs; |
158 | extern atomic_t fscache_n_allocs_intr; | 158 | extern atomic_t fscache_n_allocs_intr; |
159 | extern atomic_t fscache_n_allocs_object_dead; | ||
159 | extern atomic_t fscache_n_alloc_ops; | 160 | extern atomic_t fscache_n_alloc_ops; |
160 | extern atomic_t fscache_n_alloc_op_waits; | 161 | extern atomic_t fscache_n_alloc_op_waits; |
161 | 162 | ||
@@ -166,6 +167,7 @@ extern atomic_t fscache_n_retrievals_nodata; | |||
166 | extern atomic_t fscache_n_retrievals_nobufs; | 167 | extern atomic_t fscache_n_retrievals_nobufs; |
167 | extern atomic_t fscache_n_retrievals_intr; | 168 | extern atomic_t fscache_n_retrievals_intr; |
168 | extern atomic_t fscache_n_retrievals_nomem; | 169 | extern atomic_t fscache_n_retrievals_nomem; |
170 | extern atomic_t fscache_n_retrievals_object_dead; | ||
169 | extern atomic_t fscache_n_retrieval_ops; | 171 | extern atomic_t fscache_n_retrieval_ops; |
170 | extern atomic_t fscache_n_retrieval_op_waits; | 172 | extern atomic_t fscache_n_retrieval_op_waits; |
171 | 173 | ||
@@ -249,9 +251,12 @@ static inline void fscache_stat_d(atomic_t *stat) | |||
249 | atomic_dec(stat); | 251 | atomic_dec(stat); |
250 | } | 252 | } |
251 | 253 | ||
254 | #define __fscache_stat(stat) (stat) | ||
255 | |||
252 | extern const struct file_operations fscache_stats_fops; | 256 | extern const struct file_operations fscache_stats_fops; |
253 | #else | 257 | #else |
254 | 258 | ||
259 | #define __fscache_stat(stat) (NULL) | ||
255 | #define fscache_stat(stat) do {} while (0) | 260 | #define fscache_stat(stat) do {} while (0) |
256 | #endif | 261 | #endif |
257 | 262 | ||
diff --git a/fs/fscache/object.c b/fs/fscache/object.c index 74bc562a2cbc..c85c9f582166 100644 --- a/fs/fscache/object.c +++ b/fs/fscache/object.c | |||
@@ -201,6 +201,7 @@ static void fscache_object_state_machine(struct fscache_object *object) | |||
201 | } | 201 | } |
202 | spin_unlock(&object->lock); | 202 | spin_unlock(&object->lock); |
203 | fscache_enqueue_dependents(object); | 203 | fscache_enqueue_dependents(object); |
204 | fscache_start_operations(object); | ||
204 | goto terminal_transit; | 205 | goto terminal_transit; |
205 | 206 | ||
206 | /* handle an abort during initialisation */ | 207 | /* handle an abort during initialisation */ |
diff --git a/fs/fscache/page.c b/fs/fscache/page.c index fc76798bd968..c598ea4c4e7d 100644 --- a/fs/fscache/page.c +++ b/fs/fscache/page.c | |||
@@ -314,6 +314,43 @@ static int fscache_wait_for_deferred_lookup(struct fscache_cookie *cookie) | |||
314 | } | 314 | } |
315 | 315 | ||
316 | /* | 316 | /* |
317 | * wait for an object to become active (or dead) | ||
318 | */ | ||
319 | static int fscache_wait_for_retrieval_activation(struct fscache_object *object, | ||
320 | struct fscache_retrieval *op, | ||
321 | atomic_t *stat_op_waits, | ||
322 | atomic_t *stat_object_dead) | ||
323 | { | ||
324 | int ret; | ||
325 | |||
326 | if (!test_bit(FSCACHE_OP_WAITING, &op->op.flags)) | ||
327 | goto check_if_dead; | ||
328 | |||
329 | _debug(">>> WT"); | ||
330 | fscache_stat(stat_op_waits); | ||
331 | if (wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | ||
332 | fscache_wait_bit_interruptible, | ||
333 | TASK_INTERRUPTIBLE) < 0) { | ||
334 | ret = fscache_cancel_op(&op->op); | ||
335 | if (ret == 0) | ||
336 | return -ERESTARTSYS; | ||
337 | |||
338 | /* it's been removed from the pending queue by another party, | ||
339 | * so we should get to run shortly */ | ||
340 | wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | ||
341 | fscache_wait_bit, TASK_UNINTERRUPTIBLE); | ||
342 | } | ||
343 | _debug("<<< GO"); | ||
344 | |||
345 | check_if_dead: | ||
346 | if (unlikely(fscache_object_is_dead(object))) { | ||
347 | fscache_stat(stat_object_dead); | ||
348 | return -ENOBUFS; | ||
349 | } | ||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | /* | ||
317 | * read a page from the cache or allocate a block in which to store it | 354 | * read a page from the cache or allocate a block in which to store it |
318 | * - we return: | 355 | * - we return: |
319 | * -ENOMEM - out of memory, nothing done | 356 | * -ENOMEM - out of memory, nothing done |
@@ -376,25 +413,12 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie, | |||
376 | 413 | ||
377 | /* we wait for the operation to become active, and then process it | 414 | /* we wait for the operation to become active, and then process it |
378 | * *here*, in this thread, and not in the thread pool */ | 415 | * *here*, in this thread, and not in the thread pool */ |
379 | if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) { | 416 | ret = fscache_wait_for_retrieval_activation( |
380 | _debug(">>> WT"); | 417 | object, op, |
381 | fscache_stat(&fscache_n_retrieval_op_waits); | 418 | __fscache_stat(&fscache_n_retrieval_op_waits), |
382 | if (wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | 419 | __fscache_stat(&fscache_n_retrievals_object_dead)); |
383 | fscache_wait_bit_interruptible, | 420 | if (ret < 0) |
384 | TASK_INTERRUPTIBLE) < 0) { | 421 | goto error; |
385 | ret = fscache_cancel_op(&op->op); | ||
386 | if (ret == 0) { | ||
387 | ret = -ERESTARTSYS; | ||
388 | goto error; | ||
389 | } | ||
390 | |||
391 | /* it's been removed from the pending queue by another | ||
392 | * party, so we should get to run shortly */ | ||
393 | wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | ||
394 | fscache_wait_bit, TASK_UNINTERRUPTIBLE); | ||
395 | } | ||
396 | _debug("<<< GO"); | ||
397 | } | ||
398 | 422 | ||
399 | /* ask the cache to honour the operation */ | 423 | /* ask the cache to honour the operation */ |
400 | if (test_bit(FSCACHE_COOKIE_NO_DATA_YET, &object->cookie->flags)) { | 424 | if (test_bit(FSCACHE_COOKIE_NO_DATA_YET, &object->cookie->flags)) { |
@@ -506,25 +530,12 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie, | |||
506 | 530 | ||
507 | /* we wait for the operation to become active, and then process it | 531 | /* we wait for the operation to become active, and then process it |
508 | * *here*, in this thread, and not in the thread pool */ | 532 | * *here*, in this thread, and not in the thread pool */ |
509 | if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) { | 533 | ret = fscache_wait_for_retrieval_activation( |
510 | _debug(">>> WT"); | 534 | object, op, |
511 | fscache_stat(&fscache_n_retrieval_op_waits); | 535 | __fscache_stat(&fscache_n_retrieval_op_waits), |
512 | if (wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | 536 | __fscache_stat(&fscache_n_retrievals_object_dead)); |
513 | fscache_wait_bit_interruptible, | 537 | if (ret < 0) |
514 | TASK_INTERRUPTIBLE) < 0) { | 538 | goto error; |
515 | ret = fscache_cancel_op(&op->op); | ||
516 | if (ret == 0) { | ||
517 | ret = -ERESTARTSYS; | ||
518 | goto error; | ||
519 | } | ||
520 | |||
521 | /* it's been removed from the pending queue by another | ||
522 | * party, so we should get to run shortly */ | ||
523 | wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | ||
524 | fscache_wait_bit, TASK_UNINTERRUPTIBLE); | ||
525 | } | ||
526 | _debug("<<< GO"); | ||
527 | } | ||
528 | 539 | ||
529 | /* ask the cache to honour the operation */ | 540 | /* ask the cache to honour the operation */ |
530 | if (test_bit(FSCACHE_COOKIE_NO_DATA_YET, &object->cookie->flags)) { | 541 | if (test_bit(FSCACHE_COOKIE_NO_DATA_YET, &object->cookie->flags)) { |
@@ -612,25 +623,12 @@ int __fscache_alloc_page(struct fscache_cookie *cookie, | |||
612 | 623 | ||
613 | fscache_stat(&fscache_n_alloc_ops); | 624 | fscache_stat(&fscache_n_alloc_ops); |
614 | 625 | ||
615 | if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) { | 626 | ret = fscache_wait_for_retrieval_activation( |
616 | _debug(">>> WT"); | 627 | object, op, |
617 | fscache_stat(&fscache_n_alloc_op_waits); | 628 | __fscache_stat(&fscache_n_alloc_op_waits), |
618 | if (wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | 629 | __fscache_stat(&fscache_n_allocs_object_dead)); |
619 | fscache_wait_bit_interruptible, | 630 | if (ret < 0) |
620 | TASK_INTERRUPTIBLE) < 0) { | 631 | goto error; |
621 | ret = fscache_cancel_op(&op->op); | ||
622 | if (ret == 0) { | ||
623 | ret = -ERESTARTSYS; | ||
624 | goto error; | ||
625 | } | ||
626 | |||
627 | /* it's been removed from the pending queue by another | ||
628 | * party, so we should get to run shortly */ | ||
629 | wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | ||
630 | fscache_wait_bit, TASK_UNINTERRUPTIBLE); | ||
631 | } | ||
632 | _debug("<<< GO"); | ||
633 | } | ||
634 | 632 | ||
635 | /* ask the cache to honour the operation */ | 633 | /* ask the cache to honour the operation */ |
636 | fscache_stat(&fscache_n_cop_allocate_page); | 634 | fscache_stat(&fscache_n_cop_allocate_page); |
diff --git a/fs/fscache/stats.c b/fs/fscache/stats.c index 9e15289eb5c1..05f77caf4a2d 100644 --- a/fs/fscache/stats.c +++ b/fs/fscache/stats.c | |||
@@ -39,6 +39,7 @@ atomic_t fscache_n_allocs_ok; | |||
39 | atomic_t fscache_n_allocs_wait; | 39 | atomic_t fscache_n_allocs_wait; |
40 | atomic_t fscache_n_allocs_nobufs; | 40 | atomic_t fscache_n_allocs_nobufs; |
41 | atomic_t fscache_n_allocs_intr; | 41 | atomic_t fscache_n_allocs_intr; |
42 | atomic_t fscache_n_allocs_object_dead; | ||
42 | atomic_t fscache_n_alloc_ops; | 43 | atomic_t fscache_n_alloc_ops; |
43 | atomic_t fscache_n_alloc_op_waits; | 44 | atomic_t fscache_n_alloc_op_waits; |
44 | 45 | ||
@@ -49,6 +50,7 @@ atomic_t fscache_n_retrievals_nodata; | |||
49 | atomic_t fscache_n_retrievals_nobufs; | 50 | atomic_t fscache_n_retrievals_nobufs; |
50 | atomic_t fscache_n_retrievals_intr; | 51 | atomic_t fscache_n_retrievals_intr; |
51 | atomic_t fscache_n_retrievals_nomem; | 52 | atomic_t fscache_n_retrievals_nomem; |
53 | atomic_t fscache_n_retrievals_object_dead; | ||
52 | atomic_t fscache_n_retrieval_ops; | 54 | atomic_t fscache_n_retrieval_ops; |
53 | atomic_t fscache_n_retrieval_op_waits; | 55 | atomic_t fscache_n_retrieval_op_waits; |
54 | 56 | ||
@@ -188,9 +190,10 @@ static int fscache_stats_show(struct seq_file *m, void *v) | |||
188 | atomic_read(&fscache_n_allocs_wait), | 190 | atomic_read(&fscache_n_allocs_wait), |
189 | atomic_read(&fscache_n_allocs_nobufs), | 191 | atomic_read(&fscache_n_allocs_nobufs), |
190 | atomic_read(&fscache_n_allocs_intr)); | 192 | atomic_read(&fscache_n_allocs_intr)); |
191 | seq_printf(m, "Allocs : ops=%u owt=%u\n", | 193 | seq_printf(m, "Allocs : ops=%u owt=%u abt=%u\n", |
192 | atomic_read(&fscache_n_alloc_ops), | 194 | atomic_read(&fscache_n_alloc_ops), |
193 | atomic_read(&fscache_n_alloc_op_waits)); | 195 | atomic_read(&fscache_n_alloc_op_waits), |
196 | atomic_read(&fscache_n_allocs_object_dead)); | ||
194 | 197 | ||
195 | seq_printf(m, "Retrvls: n=%u ok=%u wt=%u nod=%u nbf=%u" | 198 | seq_printf(m, "Retrvls: n=%u ok=%u wt=%u nod=%u nbf=%u" |
196 | " int=%u oom=%u\n", | 199 | " int=%u oom=%u\n", |
@@ -201,9 +204,10 @@ static int fscache_stats_show(struct seq_file *m, void *v) | |||
201 | atomic_read(&fscache_n_retrievals_nobufs), | 204 | atomic_read(&fscache_n_retrievals_nobufs), |
202 | atomic_read(&fscache_n_retrievals_intr), | 205 | atomic_read(&fscache_n_retrievals_intr), |
203 | atomic_read(&fscache_n_retrievals_nomem)); | 206 | atomic_read(&fscache_n_retrievals_nomem)); |
204 | seq_printf(m, "Retrvls: ops=%u owt=%u\n", | 207 | seq_printf(m, "Retrvls: ops=%u owt=%u abt=%u\n", |
205 | atomic_read(&fscache_n_retrieval_ops), | 208 | atomic_read(&fscache_n_retrieval_ops), |
206 | atomic_read(&fscache_n_retrieval_op_waits)); | 209 | atomic_read(&fscache_n_retrieval_op_waits), |
210 | atomic_read(&fscache_n_retrievals_object_dead)); | ||
207 | 211 | ||
208 | seq_printf(m, "Stores : n=%u ok=%u agn=%u nbf=%u oom=%u\n", | 212 | seq_printf(m, "Stores : n=%u ok=%u agn=%u nbf=%u oom=%u\n", |
209 | atomic_read(&fscache_n_stores), | 213 | atomic_read(&fscache_n_stores), |
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index 4750d5fb419f..907bb56c5888 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h | |||
@@ -404,6 +404,10 @@ extern const char *fscache_object_states[]; | |||
404 | (obj)->state >= FSCACHE_OBJECT_AVAILABLE && \ | 404 | (obj)->state >= FSCACHE_OBJECT_AVAILABLE && \ |
405 | (obj)->state < FSCACHE_OBJECT_DYING) | 405 | (obj)->state < FSCACHE_OBJECT_DYING) |
406 | 406 | ||
407 | #define fscache_object_is_dead(obj) \ | ||
408 | (test_bit(FSCACHE_IOERROR, &(obj)->cache->flags) && \ | ||
409 | (obj)->state >= FSCACHE_OBJECT_DYING) | ||
410 | |||
407 | extern const struct slow_work_ops fscache_object_slow_work_ops; | 411 | extern const struct slow_work_ops fscache_object_slow_work_ops; |
408 | 412 | ||
409 | /** | 413 | /** |