diff options
Diffstat (limited to 'fs/fscache/cookie.c')
-rw-r--r-- | fs/fscache/cookie.c | 93 |
1 files changed, 32 insertions, 61 deletions
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c index e2cba1f60c21..0e91a3c9fdb2 100644 --- a/fs/fscache/cookie.c +++ b/fs/fscache/cookie.c | |||
@@ -95,6 +95,11 @@ struct fscache_cookie *__fscache_acquire_cookie( | |||
95 | atomic_set(&cookie->usage, 1); | 95 | atomic_set(&cookie->usage, 1); |
96 | atomic_set(&cookie->n_children, 0); | 96 | atomic_set(&cookie->n_children, 0); |
97 | 97 | ||
98 | /* We keep the active count elevated until relinquishment to prevent an | ||
99 | * attempt to wake up every time the object operations queue quiesces. | ||
100 | */ | ||
101 | atomic_set(&cookie->n_active, 1); | ||
102 | |||
98 | atomic_inc(&parent->usage); | 103 | atomic_inc(&parent->usage); |
99 | atomic_inc(&parent->n_children); | 104 | atomic_inc(&parent->n_children); |
100 | 105 | ||
@@ -177,7 +182,6 @@ static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie) | |||
177 | 182 | ||
178 | cookie->flags = | 183 | cookie->flags = |
179 | (1 << FSCACHE_COOKIE_LOOKING_UP) | | 184 | (1 << FSCACHE_COOKIE_LOOKING_UP) | |
180 | (1 << FSCACHE_COOKIE_CREATING) | | ||
181 | (1 << FSCACHE_COOKIE_NO_DATA_YET); | 185 | (1 << FSCACHE_COOKIE_NO_DATA_YET); |
182 | 186 | ||
183 | /* ask the cache to allocate objects for this cookie and its parent | 187 | /* ask the cache to allocate objects for this cookie and its parent |
@@ -205,7 +209,7 @@ static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie) | |||
205 | 209 | ||
206 | /* initiate the process of looking up all the objects in the chain | 210 | /* initiate the process of looking up all the objects in the chain |
207 | * (done by fscache_initialise_object()) */ | 211 | * (done by fscache_initialise_object()) */ |
208 | fscache_enqueue_object(object); | 212 | fscache_raise_event(object, FSCACHE_OBJECT_EV_NEW_CHILD); |
209 | 213 | ||
210 | spin_unlock(&cookie->lock); | 214 | spin_unlock(&cookie->lock); |
211 | 215 | ||
@@ -285,7 +289,7 @@ static int fscache_alloc_object(struct fscache_cache *cache, | |||
285 | 289 | ||
286 | object_already_extant: | 290 | object_already_extant: |
287 | ret = -ENOBUFS; | 291 | ret = -ENOBUFS; |
288 | if (object->state >= FSCACHE_OBJECT_DYING) { | 292 | if (fscache_object_is_dead(object)) { |
289 | spin_unlock(&cookie->lock); | 293 | spin_unlock(&cookie->lock); |
290 | goto error; | 294 | goto error; |
291 | } | 295 | } |
@@ -321,7 +325,7 @@ static int fscache_attach_object(struct fscache_cookie *cookie, | |||
321 | ret = -EEXIST; | 325 | ret = -EEXIST; |
322 | hlist_for_each_entry(p, &cookie->backing_objects, cookie_link) { | 326 | hlist_for_each_entry(p, &cookie->backing_objects, cookie_link) { |
323 | if (p->cache == object->cache) { | 327 | if (p->cache == object->cache) { |
324 | if (p->state >= FSCACHE_OBJECT_DYING) | 328 | if (fscache_object_is_dying(p)) |
325 | ret = -ENOBUFS; | 329 | ret = -ENOBUFS; |
326 | goto cant_attach_object; | 330 | goto cant_attach_object; |
327 | } | 331 | } |
@@ -332,7 +336,7 @@ static int fscache_attach_object(struct fscache_cookie *cookie, | |||
332 | hlist_for_each_entry(p, &cookie->parent->backing_objects, | 336 | hlist_for_each_entry(p, &cookie->parent->backing_objects, |
333 | cookie_link) { | 337 | cookie_link) { |
334 | if (p->cache == object->cache) { | 338 | if (p->cache == object->cache) { |
335 | if (p->state >= FSCACHE_OBJECT_DYING) { | 339 | if (fscache_object_is_dying(p)) { |
336 | ret = -ENOBUFS; | 340 | ret = -ENOBUFS; |
337 | spin_unlock(&cookie->parent->lock); | 341 | spin_unlock(&cookie->parent->lock); |
338 | goto cant_attach_object; | 342 | goto cant_attach_object; |
@@ -400,7 +404,7 @@ void __fscache_invalidate(struct fscache_cookie *cookie) | |||
400 | object = hlist_entry(cookie->backing_objects.first, | 404 | object = hlist_entry(cookie->backing_objects.first, |
401 | struct fscache_object, | 405 | struct fscache_object, |
402 | cookie_link); | 406 | cookie_link); |
403 | if (object->state < FSCACHE_OBJECT_DYING) | 407 | if (fscache_object_is_live(object)) |
404 | fscache_raise_event( | 408 | fscache_raise_event( |
405 | object, FSCACHE_OBJECT_EV_INVALIDATE); | 409 | object, FSCACHE_OBJECT_EV_INVALIDATE); |
406 | } | 410 | } |
@@ -467,9 +471,7 @@ EXPORT_SYMBOL(__fscache_update_cookie); | |||
467 | */ | 471 | */ |
468 | void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire) | 472 | void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire) |
469 | { | 473 | { |
470 | struct fscache_cache *cache; | ||
471 | struct fscache_object *object; | 474 | struct fscache_object *object; |
472 | unsigned long event; | ||
473 | 475 | ||
474 | fscache_stat(&fscache_n_relinquishes); | 476 | fscache_stat(&fscache_n_relinquishes); |
475 | if (retire) | 477 | if (retire) |
@@ -481,8 +483,11 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire) | |||
481 | return; | 483 | return; |
482 | } | 484 | } |
483 | 485 | ||
484 | _enter("%p{%s,%p},%d", | 486 | _enter("%p{%s,%p,%d},%d", |
485 | cookie, cookie->def->name, cookie->netfs_data, retire); | 487 | cookie, cookie->def->name, cookie->netfs_data, |
488 | atomic_read(&cookie->n_active), retire); | ||
489 | |||
490 | ASSERTCMP(atomic_read(&cookie->n_active), >, 0); | ||
486 | 491 | ||
487 | if (atomic_read(&cookie->n_children) != 0) { | 492 | if (atomic_read(&cookie->n_children) != 0) { |
488 | printk(KERN_ERR "FS-Cache: Cookie '%s' still has children\n", | 493 | printk(KERN_ERR "FS-Cache: Cookie '%s' still has children\n", |
@@ -490,62 +495,28 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire) | |||
490 | BUG(); | 495 | BUG(); |
491 | } | 496 | } |
492 | 497 | ||
493 | /* wait for the cookie to finish being instantiated (or to fail) */ | 498 | /* No further netfs-accessing operations on this cookie permitted */ |
494 | if (test_bit(FSCACHE_COOKIE_CREATING, &cookie->flags)) { | 499 | set_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags); |
495 | fscache_stat(&fscache_n_relinquishes_waitcrt); | 500 | if (retire) |
496 | wait_on_bit(&cookie->flags, FSCACHE_COOKIE_CREATING, | 501 | set_bit(FSCACHE_COOKIE_RETIRED, &cookie->flags); |
497 | fscache_wait_bit, TASK_UNINTERRUPTIBLE); | ||
498 | } | ||
499 | |||
500 | event = retire ? FSCACHE_OBJECT_EV_RETIRE : FSCACHE_OBJECT_EV_RELEASE; | ||
501 | 502 | ||
502 | try_again: | ||
503 | spin_lock(&cookie->lock); | 503 | spin_lock(&cookie->lock); |
504 | 504 | hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) { | |
505 | /* break links with all the active objects */ | 505 | fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL); |
506 | while (!hlist_empty(&cookie->backing_objects)) { | ||
507 | int n_reads; | ||
508 | object = hlist_entry(cookie->backing_objects.first, | ||
509 | struct fscache_object, | ||
510 | cookie_link); | ||
511 | |||
512 | _debug("RELEASE OBJ%x", object->debug_id); | ||
513 | |||
514 | set_bit(FSCACHE_COOKIE_WAITING_ON_READS, &cookie->flags); | ||
515 | n_reads = atomic_read(&object->n_reads); | ||
516 | if (n_reads) { | ||
517 | int n_ops = object->n_ops; | ||
518 | int n_in_progress = object->n_in_progress; | ||
519 | spin_unlock(&cookie->lock); | ||
520 | printk(KERN_ERR "FS-Cache:" | ||
521 | " Cookie '%s' still has %d outstanding reads (%d,%d)\n", | ||
522 | cookie->def->name, | ||
523 | n_reads, n_ops, n_in_progress); | ||
524 | wait_on_bit(&cookie->flags, FSCACHE_COOKIE_WAITING_ON_READS, | ||
525 | fscache_wait_bit, TASK_UNINTERRUPTIBLE); | ||
526 | printk("Wait finished\n"); | ||
527 | goto try_again; | ||
528 | } | ||
529 | |||
530 | /* detach each cache object from the object cookie */ | ||
531 | spin_lock(&object->lock); | ||
532 | hlist_del_init(&object->cookie_link); | ||
533 | |||
534 | cache = object->cache; | ||
535 | object->cookie = NULL; | ||
536 | fscache_raise_event(object, event); | ||
537 | spin_unlock(&object->lock); | ||
538 | |||
539 | if (atomic_dec_and_test(&cookie->usage)) | ||
540 | /* the cookie refcount shouldn't be reduced to 0 yet */ | ||
541 | BUG(); | ||
542 | } | 506 | } |
507 | spin_unlock(&cookie->lock); | ||
543 | 508 | ||
544 | /* detach pointers back to the netfs */ | 509 | /* Wait for cessation of activity requiring access to the netfs (when |
510 | * n_active reaches 0). | ||
511 | */ | ||
512 | if (!atomic_dec_and_test(&cookie->n_active)) | ||
513 | wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t, | ||
514 | TASK_UNINTERRUPTIBLE); | ||
515 | |||
516 | /* Clear pointers back to the netfs */ | ||
545 | cookie->netfs_data = NULL; | 517 | cookie->netfs_data = NULL; |
546 | cookie->def = NULL; | 518 | cookie->def = NULL; |
547 | 519 | BUG_ON(cookie->stores.rnode); | |
548 | spin_unlock(&cookie->lock); | ||
549 | 520 | ||
550 | if (cookie->parent) { | 521 | if (cookie->parent) { |
551 | ASSERTCMP(atomic_read(&cookie->parent->usage), >, 0); | 522 | ASSERTCMP(atomic_read(&cookie->parent->usage), >, 0); |
@@ -553,7 +524,7 @@ try_again: | |||
553 | atomic_dec(&cookie->parent->n_children); | 524 | atomic_dec(&cookie->parent->n_children); |
554 | } | 525 | } |
555 | 526 | ||
556 | /* finally dispose of the cookie */ | 527 | /* Dispose of the netfs's link to the cookie */ |
557 | ASSERTCMP(atomic_read(&cookie->usage), >, 0); | 528 | ASSERTCMP(atomic_read(&cookie->usage), >, 0); |
558 | fscache_cookie_put(cookie); | 529 | fscache_cookie_put(cookie); |
559 | 530 | ||