aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2009-11-19 13:11:45 -0500
committerDavid Howells <dhowells@redhat.com>2009-11-19 13:11:45 -0500
commit60d543ca724be155c2b6166e36a00c80b21bd810 (patch)
tree90ec6edd77ddb7666dbf7069aa2e001f155cea49
parentd461d26dde901b0523c46b0317e7fccf574a3933 (diff)
FS-Cache: Start processing an object's operations on that object's death
Start processing an object's operations when that object moves into the DYING state as the object cannot be destroyed until all its outstanding operations have completed. Furthermore, make sure that read and allocation operations handle being woken up on a dead object. Such events are recorded in the Allocs.abt and Retrvls.abt statistics as viewable through /proc/fs/fscache/stats. The code for waiting for object activation for the read and allocation operations is also extracted into its own function as it is much the same in all cases, differing only in the stats incremented. Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r--Documentation/filesystems/caching/fscache.txt2
-rw-r--r--fs/fscache/internal.h5
-rw-r--r--fs/fscache/object.c1
-rw-r--r--fs/fscache/page.c112
-rw-r--r--fs/fscache/stats.c12
-rw-r--r--include/linux/fscache-cache.h4
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;
156extern atomic_t fscache_n_allocs_wait; 156extern atomic_t fscache_n_allocs_wait;
157extern atomic_t fscache_n_allocs_nobufs; 157extern atomic_t fscache_n_allocs_nobufs;
158extern atomic_t fscache_n_allocs_intr; 158extern atomic_t fscache_n_allocs_intr;
159extern atomic_t fscache_n_allocs_object_dead;
159extern atomic_t fscache_n_alloc_ops; 160extern atomic_t fscache_n_alloc_ops;
160extern atomic_t fscache_n_alloc_op_waits; 161extern atomic_t fscache_n_alloc_op_waits;
161 162
@@ -166,6 +167,7 @@ extern atomic_t fscache_n_retrievals_nodata;
166extern atomic_t fscache_n_retrievals_nobufs; 167extern atomic_t fscache_n_retrievals_nobufs;
167extern atomic_t fscache_n_retrievals_intr; 168extern atomic_t fscache_n_retrievals_intr;
168extern atomic_t fscache_n_retrievals_nomem; 169extern atomic_t fscache_n_retrievals_nomem;
170extern atomic_t fscache_n_retrievals_object_dead;
169extern atomic_t fscache_n_retrieval_ops; 171extern atomic_t fscache_n_retrieval_ops;
170extern atomic_t fscache_n_retrieval_op_waits; 172extern 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
252extern const struct file_operations fscache_stats_fops; 256extern 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 */
319static 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
345check_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;
39atomic_t fscache_n_allocs_wait; 39atomic_t fscache_n_allocs_wait;
40atomic_t fscache_n_allocs_nobufs; 40atomic_t fscache_n_allocs_nobufs;
41atomic_t fscache_n_allocs_intr; 41atomic_t fscache_n_allocs_intr;
42atomic_t fscache_n_allocs_object_dead;
42atomic_t fscache_n_alloc_ops; 43atomic_t fscache_n_alloc_ops;
43atomic_t fscache_n_alloc_op_waits; 44atomic_t fscache_n_alloc_op_waits;
44 45
@@ -49,6 +50,7 @@ atomic_t fscache_n_retrievals_nodata;
49atomic_t fscache_n_retrievals_nobufs; 50atomic_t fscache_n_retrievals_nobufs;
50atomic_t fscache_n_retrievals_intr; 51atomic_t fscache_n_retrievals_intr;
51atomic_t fscache_n_retrievals_nomem; 52atomic_t fscache_n_retrievals_nomem;
53atomic_t fscache_n_retrievals_object_dead;
52atomic_t fscache_n_retrieval_ops; 54atomic_t fscache_n_retrieval_ops;
53atomic_t fscache_n_retrieval_op_waits; 55atomic_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
407extern const struct slow_work_ops fscache_object_slow_work_ops; 411extern const struct slow_work_ops fscache_object_slow_work_ops;
408 412
409/** 413/**