diff options
author | Tejun Heo <tj@kernel.org> | 2010-07-20 16:09:01 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2010-07-22 16:58:34 -0400 |
commit | 8b8edefa2fffbff97f9eec8b70e78ae23abad1a0 (patch) | |
tree | 7f0efac8adb9c9ed7be8af63e51510954f1c51dc /fs/fscache/object.c | |
parent | e120153ddf8620fd0a194d301e9c5a8b28483bb5 (diff) |
fscache: convert object to use workqueue instead of slow-work
Make fscache object state transition callbacks use workqueue instead
of slow-work. New dedicated unbound CPU workqueue fscache_object_wq
is created. get/put callbacks are renamed and modified to take
@object and called directly from the enqueue wrapper and the work
function. While at it, make all open coded instances of get/put to
use fscache_get/put_object().
* Unbound workqueue is used.
* work_busy() output is printed instead of slow-work flags in object
debugging outputs. They mean basically the same thing bit-for-bit.
* sysctl fscache.object_max_active added to control concurrency. The
default value is nr_cpus clamped between 4 and
WQ_UNBOUND_MAX_ACTIVE.
* slow_work_sleep_till_thread_needed() is replaced with fscache
private implementation fscache_object_sleep_till_congested() which
waits on fscache_object_wq congestion.
* debugfs support is dropped for now. Tracing API based debug
facility is planned to be added.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/fscache/object.c')
-rw-r--r-- | fs/fscache/object.c | 106 |
1 files changed, 53 insertions, 53 deletions
diff --git a/fs/fscache/object.c b/fs/fscache/object.c index 0b589a9b4ffc..b6b897c550ac 100644 --- a/fs/fscache/object.c +++ b/fs/fscache/object.c | |||
@@ -14,7 +14,6 @@ | |||
14 | 14 | ||
15 | #define FSCACHE_DEBUG_LEVEL COOKIE | 15 | #define FSCACHE_DEBUG_LEVEL COOKIE |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/seq_file.h> | ||
18 | #include "internal.h" | 17 | #include "internal.h" |
19 | 18 | ||
20 | const char *fscache_object_states[FSCACHE_OBJECT__NSTATES] = { | 19 | const char *fscache_object_states[FSCACHE_OBJECT__NSTATES] = { |
@@ -50,12 +49,8 @@ const char fscache_object_states_short[FSCACHE_OBJECT__NSTATES][5] = { | |||
50 | [FSCACHE_OBJECT_DEAD] = "DEAD", | 49 | [FSCACHE_OBJECT_DEAD] = "DEAD", |
51 | }; | 50 | }; |
52 | 51 | ||
53 | static void fscache_object_slow_work_put_ref(struct slow_work *); | 52 | static int fscache_get_object(struct fscache_object *); |
54 | static int fscache_object_slow_work_get_ref(struct slow_work *); | 53 | static void fscache_put_object(struct fscache_object *); |
55 | static void fscache_object_slow_work_execute(struct slow_work *); | ||
56 | #ifdef CONFIG_SLOW_WORK_DEBUG | ||
57 | static void fscache_object_slow_work_desc(struct slow_work *, struct seq_file *); | ||
58 | #endif | ||
59 | static void fscache_initialise_object(struct fscache_object *); | 54 | static void fscache_initialise_object(struct fscache_object *); |
60 | static void fscache_lookup_object(struct fscache_object *); | 55 | static void fscache_lookup_object(struct fscache_object *); |
61 | static void fscache_object_available(struct fscache_object *); | 56 | static void fscache_object_available(struct fscache_object *); |
@@ -64,17 +59,6 @@ static void fscache_withdraw_object(struct fscache_object *); | |||
64 | static void fscache_enqueue_dependents(struct fscache_object *); | 59 | static void fscache_enqueue_dependents(struct fscache_object *); |
65 | static void fscache_dequeue_object(struct fscache_object *); | 60 | static void fscache_dequeue_object(struct fscache_object *); |
66 | 61 | ||
67 | const struct slow_work_ops fscache_object_slow_work_ops = { | ||
68 | .owner = THIS_MODULE, | ||
69 | .get_ref = fscache_object_slow_work_get_ref, | ||
70 | .put_ref = fscache_object_slow_work_put_ref, | ||
71 | .execute = fscache_object_slow_work_execute, | ||
72 | #ifdef CONFIG_SLOW_WORK_DEBUG | ||
73 | .desc = fscache_object_slow_work_desc, | ||
74 | #endif | ||
75 | }; | ||
76 | EXPORT_SYMBOL(fscache_object_slow_work_ops); | ||
77 | |||
78 | /* | 62 | /* |
79 | * we need to notify the parent when an op completes that we had outstanding | 63 | * we need to notify the parent when an op completes that we had outstanding |
80 | * upon it | 64 | * upon it |
@@ -345,7 +329,7 @@ unsupported_event: | |||
345 | /* | 329 | /* |
346 | * execute an object | 330 | * execute an object |
347 | */ | 331 | */ |
348 | static void fscache_object_slow_work_execute(struct slow_work *work) | 332 | void fscache_object_work_func(struct work_struct *work) |
349 | { | 333 | { |
350 | struct fscache_object *object = | 334 | struct fscache_object *object = |
351 | container_of(work, struct fscache_object, work); | 335 | container_of(work, struct fscache_object, work); |
@@ -359,23 +343,9 @@ static void fscache_object_slow_work_execute(struct slow_work *work) | |||
359 | if (object->events & object->event_mask) | 343 | if (object->events & object->event_mask) |
360 | fscache_enqueue_object(object); | 344 | fscache_enqueue_object(object); |
361 | clear_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events); | 345 | clear_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events); |
346 | fscache_put_object(object); | ||
362 | } | 347 | } |
363 | 348 | EXPORT_SYMBOL(fscache_object_work_func); | |
364 | /* | ||
365 | * describe an object for slow-work debugging | ||
366 | */ | ||
367 | #ifdef CONFIG_SLOW_WORK_DEBUG | ||
368 | static void fscache_object_slow_work_desc(struct slow_work *work, | ||
369 | struct seq_file *m) | ||
370 | { | ||
371 | struct fscache_object *object = | ||
372 | container_of(work, struct fscache_object, work); | ||
373 | |||
374 | seq_printf(m, "FSC: OBJ%x: %s", | ||
375 | object->debug_id, | ||
376 | fscache_object_states_short[object->state]); | ||
377 | } | ||
378 | #endif | ||
379 | 349 | ||
380 | /* | 350 | /* |
381 | * initialise an object | 351 | * initialise an object |
@@ -393,7 +363,6 @@ static void fscache_initialise_object(struct fscache_object *object) | |||
393 | _enter(""); | 363 | _enter(""); |
394 | ASSERT(object->cookie != NULL); | 364 | ASSERT(object->cookie != NULL); |
395 | ASSERT(object->cookie->parent != NULL); | 365 | ASSERT(object->cookie->parent != NULL); |
396 | ASSERT(list_empty(&object->work.link)); | ||
397 | 366 | ||
398 | if (object->events & ((1 << FSCACHE_OBJECT_EV_ERROR) | | 367 | if (object->events & ((1 << FSCACHE_OBJECT_EV_ERROR) | |
399 | (1 << FSCACHE_OBJECT_EV_RELEASE) | | 368 | (1 << FSCACHE_OBJECT_EV_RELEASE) | |
@@ -671,10 +640,8 @@ static void fscache_drop_object(struct fscache_object *object) | |||
671 | object->parent = NULL; | 640 | object->parent = NULL; |
672 | } | 641 | } |
673 | 642 | ||
674 | /* this just shifts the object release to the slow work processor */ | 643 | /* this just shifts the object release to the work processor */ |
675 | fscache_stat(&fscache_n_cop_put_object); | 644 | fscache_put_object(object); |
676 | object->cache->ops->put_object(object); | ||
677 | fscache_stat_d(&fscache_n_cop_put_object); | ||
678 | 645 | ||
679 | _leave(""); | 646 | _leave(""); |
680 | } | 647 | } |
@@ -758,12 +725,10 @@ void fscache_withdrawing_object(struct fscache_cache *cache, | |||
758 | } | 725 | } |
759 | 726 | ||
760 | /* | 727 | /* |
761 | * allow the slow work item processor to get a ref on an object | 728 | * get a ref on an object |
762 | */ | 729 | */ |
763 | static int fscache_object_slow_work_get_ref(struct slow_work *work) | 730 | static int fscache_get_object(struct fscache_object *object) |
764 | { | 731 | { |
765 | struct fscache_object *object = | ||
766 | container_of(work, struct fscache_object, work); | ||
767 | int ret; | 732 | int ret; |
768 | 733 | ||
769 | fscache_stat(&fscache_n_cop_grab_object); | 734 | fscache_stat(&fscache_n_cop_grab_object); |
@@ -773,13 +738,10 @@ static int fscache_object_slow_work_get_ref(struct slow_work *work) | |||
773 | } | 738 | } |
774 | 739 | ||
775 | /* | 740 | /* |
776 | * allow the slow work item processor to discard a ref on a work item | 741 | * discard a ref on a work item |
777 | */ | 742 | */ |
778 | static void fscache_object_slow_work_put_ref(struct slow_work *work) | 743 | static void fscache_put_object(struct fscache_object *object) |
779 | { | 744 | { |
780 | struct fscache_object *object = | ||
781 | container_of(work, struct fscache_object, work); | ||
782 | |||
783 | fscache_stat(&fscache_n_cop_put_object); | 745 | fscache_stat(&fscache_n_cop_put_object); |
784 | object->cache->ops->put_object(object); | 746 | object->cache->ops->put_object(object); |
785 | fscache_stat_d(&fscache_n_cop_put_object); | 747 | fscache_stat_d(&fscache_n_cop_put_object); |
@@ -792,8 +754,48 @@ void fscache_enqueue_object(struct fscache_object *object) | |||
792 | { | 754 | { |
793 | _enter("{OBJ%x}", object->debug_id); | 755 | _enter("{OBJ%x}", object->debug_id); |
794 | 756 | ||
795 | slow_work_enqueue(&object->work); | 757 | if (fscache_get_object(object) >= 0) { |
758 | wait_queue_head_t *cong_wq = | ||
759 | &get_cpu_var(fscache_object_cong_wait); | ||
760 | |||
761 | if (queue_work(fscache_object_wq, &object->work)) { | ||
762 | if (fscache_object_congested()) | ||
763 | wake_up(cong_wq); | ||
764 | } else | ||
765 | fscache_put_object(object); | ||
766 | |||
767 | put_cpu_var(fscache_object_cong_wait); | ||
768 | } | ||
769 | } | ||
770 | |||
771 | /** | ||
772 | * fscache_object_sleep_till_congested - Sleep until object wq is congested | ||
773 | * @timoutp: Scheduler sleep timeout | ||
774 | * | ||
775 | * Allow an object handler to sleep until the object workqueue is congested. | ||
776 | * | ||
777 | * The caller must set up a wake up event before calling this and must have set | ||
778 | * the appropriate sleep mode (such as TASK_UNINTERRUPTIBLE) and tested its own | ||
779 | * condition before calling this function as no test is made here. | ||
780 | * | ||
781 | * %true is returned if the object wq is congested, %false otherwise. | ||
782 | */ | ||
783 | bool fscache_object_sleep_till_congested(signed long *timeoutp) | ||
784 | { | ||
785 | wait_queue_head_t *cong_wq = &__get_cpu_var(fscache_object_cong_wait); | ||
786 | DEFINE_WAIT(wait); | ||
787 | |||
788 | if (fscache_object_congested()) | ||
789 | return true; | ||
790 | |||
791 | add_wait_queue_exclusive(cong_wq, &wait); | ||
792 | if (!fscache_object_congested()) | ||
793 | *timeoutp = schedule_timeout(*timeoutp); | ||
794 | finish_wait(cong_wq, &wait); | ||
795 | |||
796 | return fscache_object_congested(); | ||
796 | } | 797 | } |
798 | EXPORT_SYMBOL_GPL(fscache_object_sleep_till_congested); | ||
797 | 799 | ||
798 | /* | 800 | /* |
799 | * enqueue the dependents of an object for metadata-type processing | 801 | * enqueue the dependents of an object for metadata-type processing |
@@ -819,9 +821,7 @@ static void fscache_enqueue_dependents(struct fscache_object *object) | |||
819 | 821 | ||
820 | /* sort onto appropriate lists */ | 822 | /* sort onto appropriate lists */ |
821 | fscache_enqueue_object(dep); | 823 | fscache_enqueue_object(dep); |
822 | fscache_stat(&fscache_n_cop_put_object); | 824 | fscache_put_object(dep); |
823 | dep->cache->ops->put_object(dep); | ||
824 | fscache_stat_d(&fscache_n_cop_put_object); | ||
825 | 825 | ||
826 | if (!list_empty(&object->dependents)) | 826 | if (!list_empty(&object->dependents)) |
827 | cond_resched_lock(&object->lock); | 827 | cond_resched_lock(&object->lock); |