diff options
Diffstat (limited to 'fs/fscache/object.c')
| -rw-r--r-- | fs/fscache/object.c | 104 |
1 files changed, 93 insertions, 11 deletions
diff --git a/fs/fscache/object.c b/fs/fscache/object.c index 392a41b1b79d..e513ac599c8e 100644 --- a/fs/fscache/object.c +++ b/fs/fscache/object.c | |||
| @@ -14,9 +14,10 @@ | |||
| 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> | ||
| 17 | #include "internal.h" | 18 | #include "internal.h" |
| 18 | 19 | ||
| 19 | const char *fscache_object_states[] = { | 20 | const char *fscache_object_states[FSCACHE_OBJECT__NSTATES] = { |
| 20 | [FSCACHE_OBJECT_INIT] = "OBJECT_INIT", | 21 | [FSCACHE_OBJECT_INIT] = "OBJECT_INIT", |
| 21 | [FSCACHE_OBJECT_LOOKING_UP] = "OBJECT_LOOKING_UP", | 22 | [FSCACHE_OBJECT_LOOKING_UP] = "OBJECT_LOOKING_UP", |
| 22 | [FSCACHE_OBJECT_CREATING] = "OBJECT_CREATING", | 23 | [FSCACHE_OBJECT_CREATING] = "OBJECT_CREATING", |
| @@ -33,9 +34,28 @@ const char *fscache_object_states[] = { | |||
| 33 | }; | 34 | }; |
| 34 | EXPORT_SYMBOL(fscache_object_states); | 35 | EXPORT_SYMBOL(fscache_object_states); |
| 35 | 36 | ||
| 37 | const char fscache_object_states_short[FSCACHE_OBJECT__NSTATES][5] = { | ||
| 38 | [FSCACHE_OBJECT_INIT] = "INIT", | ||
| 39 | [FSCACHE_OBJECT_LOOKING_UP] = "LOOK", | ||
| 40 | [FSCACHE_OBJECT_CREATING] = "CRTN", | ||
| 41 | [FSCACHE_OBJECT_AVAILABLE] = "AVBL", | ||
| 42 | [FSCACHE_OBJECT_ACTIVE] = "ACTV", | ||
| 43 | [FSCACHE_OBJECT_UPDATING] = "UPDT", | ||
| 44 | [FSCACHE_OBJECT_DYING] = "DYNG", | ||
| 45 | [FSCACHE_OBJECT_LC_DYING] = "LCDY", | ||
| 46 | [FSCACHE_OBJECT_ABORT_INIT] = "ABTI", | ||
| 47 | [FSCACHE_OBJECT_RELEASING] = "RELS", | ||
| 48 | [FSCACHE_OBJECT_RECYCLING] = "RCYC", | ||
| 49 | [FSCACHE_OBJECT_WITHDRAWING] = "WTHD", | ||
| 50 | [FSCACHE_OBJECT_DEAD] = "DEAD", | ||
| 51 | }; | ||
| 52 | |||
| 36 | static void fscache_object_slow_work_put_ref(struct slow_work *); | 53 | static void fscache_object_slow_work_put_ref(struct slow_work *); |
| 37 | static int fscache_object_slow_work_get_ref(struct slow_work *); | 54 | static int fscache_object_slow_work_get_ref(struct slow_work *); |
| 38 | static void fscache_object_slow_work_execute(struct slow_work *); | 55 | static void fscache_object_slow_work_execute(struct slow_work *); |
| 56 | #ifdef CONFIG_SLOW_WORK_PROC | ||
| 57 | static void fscache_object_slow_work_desc(struct slow_work *, struct seq_file *); | ||
| 58 | #endif | ||
| 39 | static void fscache_initialise_object(struct fscache_object *); | 59 | static void fscache_initialise_object(struct fscache_object *); |
| 40 | static void fscache_lookup_object(struct fscache_object *); | 60 | static void fscache_lookup_object(struct fscache_object *); |
| 41 | static void fscache_object_available(struct fscache_object *); | 61 | static void fscache_object_available(struct fscache_object *); |
| @@ -45,9 +65,13 @@ static void fscache_enqueue_dependents(struct fscache_object *); | |||
| 45 | static void fscache_dequeue_object(struct fscache_object *); | 65 | static void fscache_dequeue_object(struct fscache_object *); |
| 46 | 66 | ||
| 47 | const struct slow_work_ops fscache_object_slow_work_ops = { | 67 | const struct slow_work_ops fscache_object_slow_work_ops = { |
| 68 | .owner = THIS_MODULE, | ||
| 48 | .get_ref = fscache_object_slow_work_get_ref, | 69 | .get_ref = fscache_object_slow_work_get_ref, |
| 49 | .put_ref = fscache_object_slow_work_put_ref, | 70 | .put_ref = fscache_object_slow_work_put_ref, |
| 50 | .execute = fscache_object_slow_work_execute, | 71 | .execute = fscache_object_slow_work_execute, |
| 72 | #ifdef CONFIG_SLOW_WORK_PROC | ||
| 73 | .desc = fscache_object_slow_work_desc, | ||
| 74 | #endif | ||
| 51 | }; | 75 | }; |
| 52 | EXPORT_SYMBOL(fscache_object_slow_work_ops); | 76 | EXPORT_SYMBOL(fscache_object_slow_work_ops); |
| 53 | 77 | ||
| @@ -81,6 +105,7 @@ static inline void fscache_done_parent_op(struct fscache_object *object) | |||
| 81 | static void fscache_object_state_machine(struct fscache_object *object) | 105 | static void fscache_object_state_machine(struct fscache_object *object) |
| 82 | { | 106 | { |
| 83 | enum fscache_object_state new_state; | 107 | enum fscache_object_state new_state; |
| 108 | struct fscache_cookie *cookie; | ||
| 84 | 109 | ||
| 85 | ASSERT(object != NULL); | 110 | ASSERT(object != NULL); |
| 86 | 111 | ||
| @@ -120,20 +145,31 @@ static void fscache_object_state_machine(struct fscache_object *object) | |||
| 120 | case FSCACHE_OBJECT_UPDATING: | 145 | case FSCACHE_OBJECT_UPDATING: |
| 121 | clear_bit(FSCACHE_OBJECT_EV_UPDATE, &object->events); | 146 | clear_bit(FSCACHE_OBJECT_EV_UPDATE, &object->events); |
| 122 | fscache_stat(&fscache_n_updates_run); | 147 | fscache_stat(&fscache_n_updates_run); |
| 148 | fscache_stat(&fscache_n_cop_update_object); | ||
| 123 | object->cache->ops->update_object(object); | 149 | object->cache->ops->update_object(object); |
| 150 | fscache_stat_d(&fscache_n_cop_update_object); | ||
| 124 | goto active_transit; | 151 | goto active_transit; |
| 125 | 152 | ||
| 126 | /* handle an object dying during lookup or creation */ | 153 | /* handle an object dying during lookup or creation */ |
| 127 | case FSCACHE_OBJECT_LC_DYING: | 154 | case FSCACHE_OBJECT_LC_DYING: |
| 128 | object->event_mask &= ~(1 << FSCACHE_OBJECT_EV_UPDATE); | 155 | object->event_mask &= ~(1 << FSCACHE_OBJECT_EV_UPDATE); |
| 156 | fscache_stat(&fscache_n_cop_lookup_complete); | ||
| 129 | object->cache->ops->lookup_complete(object); | 157 | object->cache->ops->lookup_complete(object); |
| 158 | fscache_stat_d(&fscache_n_cop_lookup_complete); | ||
| 130 | 159 | ||
| 131 | spin_lock(&object->lock); | 160 | spin_lock(&object->lock); |
| 132 | object->state = FSCACHE_OBJECT_DYING; | 161 | object->state = FSCACHE_OBJECT_DYING; |
| 133 | if (test_and_clear_bit(FSCACHE_COOKIE_CREATING, | 162 | cookie = object->cookie; |
| 134 | &object->cookie->flags)) | 163 | if (cookie) { |
| 135 | wake_up_bit(&object->cookie->flags, | 164 | if (test_and_clear_bit(FSCACHE_COOKIE_LOOKING_UP, |
| 136 | FSCACHE_COOKIE_CREATING); | 165 | &cookie->flags)) |
| 166 | wake_up_bit(&cookie->flags, | ||
| 167 | FSCACHE_COOKIE_LOOKING_UP); | ||
| 168 | if (test_and_clear_bit(FSCACHE_COOKIE_CREATING, | ||
| 169 | &cookie->flags)) | ||
| 170 | wake_up_bit(&cookie->flags, | ||
| 171 | FSCACHE_COOKIE_CREATING); | ||
| 172 | } | ||
| 137 | spin_unlock(&object->lock); | 173 | spin_unlock(&object->lock); |
| 138 | 174 | ||
| 139 | fscache_done_parent_op(object); | 175 | fscache_done_parent_op(object); |
| @@ -165,6 +201,7 @@ static void fscache_object_state_machine(struct fscache_object *object) | |||
| 165 | } | 201 | } |
| 166 | spin_unlock(&object->lock); | 202 | spin_unlock(&object->lock); |
| 167 | fscache_enqueue_dependents(object); | 203 | fscache_enqueue_dependents(object); |
| 204 | fscache_start_operations(object); | ||
| 168 | goto terminal_transit; | 205 | goto terminal_transit; |
| 169 | 206 | ||
| 170 | /* handle an abort during initialisation */ | 207 | /* handle an abort during initialisation */ |
| @@ -316,14 +353,29 @@ static void fscache_object_slow_work_execute(struct slow_work *work) | |||
| 316 | 353 | ||
| 317 | _enter("{OBJ%x}", object->debug_id); | 354 | _enter("{OBJ%x}", object->debug_id); |
| 318 | 355 | ||
| 319 | clear_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events); | ||
| 320 | |||
| 321 | start = jiffies; | 356 | start = jiffies; |
| 322 | fscache_object_state_machine(object); | 357 | fscache_object_state_machine(object); |
| 323 | fscache_hist(fscache_objs_histogram, start); | 358 | fscache_hist(fscache_objs_histogram, start); |
| 324 | if (object->events & object->event_mask) | 359 | if (object->events & object->event_mask) |
| 325 | fscache_enqueue_object(object); | 360 | fscache_enqueue_object(object); |
| 361 | clear_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events); | ||
| 362 | } | ||
| 363 | |||
| 364 | /* | ||
| 365 | * describe an object for slow-work debugging | ||
| 366 | */ | ||
| 367 | #ifdef CONFIG_SLOW_WORK_PROC | ||
| 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]); | ||
| 326 | } | 377 | } |
| 378 | #endif | ||
| 327 | 379 | ||
| 328 | /* | 380 | /* |
| 329 | * initialise an object | 381 | * initialise an object |
| @@ -376,7 +428,9 @@ static void fscache_initialise_object(struct fscache_object *object) | |||
| 376 | * binding on to us, so we need to make sure we don't | 428 | * binding on to us, so we need to make sure we don't |
| 377 | * add ourself to the list multiple times */ | 429 | * add ourself to the list multiple times */ |
| 378 | if (list_empty(&object->dep_link)) { | 430 | if (list_empty(&object->dep_link)) { |
| 431 | fscache_stat(&fscache_n_cop_grab_object); | ||
| 379 | object->cache->ops->grab_object(object); | 432 | object->cache->ops->grab_object(object); |
| 433 | fscache_stat_d(&fscache_n_cop_grab_object); | ||
| 380 | list_add(&object->dep_link, | 434 | list_add(&object->dep_link, |
| 381 | &parent->dependents); | 435 | &parent->dependents); |
| 382 | 436 | ||
| @@ -414,6 +468,7 @@ static void fscache_lookup_object(struct fscache_object *object) | |||
| 414 | { | 468 | { |
| 415 | struct fscache_cookie *cookie = object->cookie; | 469 | struct fscache_cookie *cookie = object->cookie; |
| 416 | struct fscache_object *parent; | 470 | struct fscache_object *parent; |
| 471 | int ret; | ||
| 417 | 472 | ||
| 418 | _enter(""); | 473 | _enter(""); |
| 419 | 474 | ||
| @@ -438,11 +493,20 @@ static void fscache_lookup_object(struct fscache_object *object) | |||
| 438 | object->cache->tag->name); | 493 | object->cache->tag->name); |
| 439 | 494 | ||
| 440 | fscache_stat(&fscache_n_object_lookups); | 495 | fscache_stat(&fscache_n_object_lookups); |
| 441 | object->cache->ops->lookup_object(object); | 496 | fscache_stat(&fscache_n_cop_lookup_object); |
| 497 | ret = object->cache->ops->lookup_object(object); | ||
| 498 | fscache_stat_d(&fscache_n_cop_lookup_object); | ||
| 442 | 499 | ||
| 443 | if (test_bit(FSCACHE_OBJECT_EV_ERROR, &object->events)) | 500 | if (test_bit(FSCACHE_OBJECT_EV_ERROR, &object->events)) |
| 444 | set_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags); | 501 | set_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags); |
| 445 | 502 | ||
| 503 | if (ret == -ETIMEDOUT) { | ||
| 504 | /* probably stuck behind another object, so move this one to | ||
| 505 | * the back of the queue */ | ||
| 506 | fscache_stat(&fscache_n_object_lookups_timed_out); | ||
| 507 | set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events); | ||
| 508 | } | ||
| 509 | |||
| 446 | _leave(""); | 510 | _leave(""); |
| 447 | } | 511 | } |
| 448 | 512 | ||
| @@ -546,7 +610,8 @@ static void fscache_object_available(struct fscache_object *object) | |||
| 546 | 610 | ||
| 547 | spin_lock(&object->lock); | 611 | spin_lock(&object->lock); |
| 548 | 612 | ||
| 549 | if (test_and_clear_bit(FSCACHE_COOKIE_CREATING, &object->cookie->flags)) | 613 | if (object->cookie && |
| 614 | test_and_clear_bit(FSCACHE_COOKIE_CREATING, &object->cookie->flags)) | ||
| 550 | wake_up_bit(&object->cookie->flags, FSCACHE_COOKIE_CREATING); | 615 | wake_up_bit(&object->cookie->flags, FSCACHE_COOKIE_CREATING); |
| 551 | 616 | ||
| 552 | fscache_done_parent_op(object); | 617 | fscache_done_parent_op(object); |
| @@ -562,7 +627,9 @@ static void fscache_object_available(struct fscache_object *object) | |||
| 562 | } | 627 | } |
| 563 | spin_unlock(&object->lock); | 628 | spin_unlock(&object->lock); |
| 564 | 629 | ||
| 630 | fscache_stat(&fscache_n_cop_lookup_complete); | ||
| 565 | object->cache->ops->lookup_complete(object); | 631 | object->cache->ops->lookup_complete(object); |
| 632 | fscache_stat_d(&fscache_n_cop_lookup_complete); | ||
| 566 | fscache_enqueue_dependents(object); | 633 | fscache_enqueue_dependents(object); |
| 567 | 634 | ||
| 568 | fscache_hist(fscache_obj_instantiate_histogram, object->lookup_jif); | 635 | fscache_hist(fscache_obj_instantiate_histogram, object->lookup_jif); |
| @@ -581,11 +648,16 @@ static void fscache_drop_object(struct fscache_object *object) | |||
| 581 | 648 | ||
| 582 | _enter("{OBJ%x,%d}", object->debug_id, object->n_children); | 649 | _enter("{OBJ%x,%d}", object->debug_id, object->n_children); |
| 583 | 650 | ||
| 651 | ASSERTCMP(object->cookie, ==, NULL); | ||
| 652 | ASSERT(hlist_unhashed(&object->cookie_link)); | ||
| 653 | |||
| 584 | spin_lock(&cache->object_list_lock); | 654 | spin_lock(&cache->object_list_lock); |
| 585 | list_del_init(&object->cache_link); | 655 | list_del_init(&object->cache_link); |
| 586 | spin_unlock(&cache->object_list_lock); | 656 | spin_unlock(&cache->object_list_lock); |
| 587 | 657 | ||
| 658 | fscache_stat(&fscache_n_cop_drop_object); | ||
| 588 | cache->ops->drop_object(object); | 659 | cache->ops->drop_object(object); |
| 660 | fscache_stat_d(&fscache_n_cop_drop_object); | ||
| 589 | 661 | ||
| 590 | if (parent) { | 662 | if (parent) { |
| 591 | _debug("release parent OBJ%x {%d}", | 663 | _debug("release parent OBJ%x {%d}", |
| @@ -600,7 +672,9 @@ static void fscache_drop_object(struct fscache_object *object) | |||
| 600 | } | 672 | } |
| 601 | 673 | ||
| 602 | /* this just shifts the object release to the slow work processor */ | 674 | /* this just shifts the object release to the slow work processor */ |
| 675 | fscache_stat(&fscache_n_cop_put_object); | ||
| 603 | object->cache->ops->put_object(object); | 676 | object->cache->ops->put_object(object); |
| 677 | fscache_stat_d(&fscache_n_cop_put_object); | ||
| 604 | 678 | ||
| 605 | _leave(""); | 679 | _leave(""); |
| 606 | } | 680 | } |
| @@ -690,8 +764,12 @@ static int fscache_object_slow_work_get_ref(struct slow_work *work) | |||
| 690 | { | 764 | { |
| 691 | struct fscache_object *object = | 765 | struct fscache_object *object = |
| 692 | container_of(work, struct fscache_object, work); | 766 | container_of(work, struct fscache_object, work); |
| 767 | int ret; | ||
| 693 | 768 | ||
| 694 | return object->cache->ops->grab_object(object) ? 0 : -EAGAIN; | 769 | fscache_stat(&fscache_n_cop_grab_object); |
| 770 | ret = object->cache->ops->grab_object(object) ? 0 : -EAGAIN; | ||
| 771 | fscache_stat_d(&fscache_n_cop_grab_object); | ||
| 772 | return ret; | ||
| 695 | } | 773 | } |
| 696 | 774 | ||
| 697 | /* | 775 | /* |
| @@ -702,7 +780,9 @@ static void fscache_object_slow_work_put_ref(struct slow_work *work) | |||
| 702 | struct fscache_object *object = | 780 | struct fscache_object *object = |
| 703 | container_of(work, struct fscache_object, work); | 781 | container_of(work, struct fscache_object, work); |
| 704 | 782 | ||
| 705 | return object->cache->ops->put_object(object); | 783 | fscache_stat(&fscache_n_cop_put_object); |
| 784 | object->cache->ops->put_object(object); | ||
| 785 | fscache_stat_d(&fscache_n_cop_put_object); | ||
| 706 | } | 786 | } |
| 707 | 787 | ||
| 708 | /* | 788 | /* |
| @@ -739,7 +819,9 @@ static void fscache_enqueue_dependents(struct fscache_object *object) | |||
| 739 | 819 | ||
| 740 | /* sort onto appropriate lists */ | 820 | /* sort onto appropriate lists */ |
| 741 | fscache_enqueue_object(dep); | 821 | fscache_enqueue_object(dep); |
| 822 | fscache_stat(&fscache_n_cop_put_object); | ||
| 742 | dep->cache->ops->put_object(dep); | 823 | dep->cache->ops->put_object(dep); |
| 824 | fscache_stat_d(&fscache_n_cop_put_object); | ||
| 743 | 825 | ||
| 744 | if (!list_empty(&object->dependents)) | 826 | if (!list_empty(&object->dependents)) |
| 745 | cond_resched_lock(&object->lock); | 827 | cond_resched_lock(&object->lock); |
