at v2.6.32-rc7 810 lines 23 kB view raw
1/* FS-Cache object state machine handler 2 * 3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 * 11 * See Documentation/filesystems/caching/object.txt for a description of the 12 * object state machine and the in-kernel representations. 13 */ 14 15#define FSCACHE_DEBUG_LEVEL COOKIE 16#include <linux/module.h> 17#include "internal.h" 18 19const char *fscache_object_states[] = { 20 [FSCACHE_OBJECT_INIT] = "OBJECT_INIT", 21 [FSCACHE_OBJECT_LOOKING_UP] = "OBJECT_LOOKING_UP", 22 [FSCACHE_OBJECT_CREATING] = "OBJECT_CREATING", 23 [FSCACHE_OBJECT_AVAILABLE] = "OBJECT_AVAILABLE", 24 [FSCACHE_OBJECT_ACTIVE] = "OBJECT_ACTIVE", 25 [FSCACHE_OBJECT_UPDATING] = "OBJECT_UPDATING", 26 [FSCACHE_OBJECT_DYING] = "OBJECT_DYING", 27 [FSCACHE_OBJECT_LC_DYING] = "OBJECT_LC_DYING", 28 [FSCACHE_OBJECT_ABORT_INIT] = "OBJECT_ABORT_INIT", 29 [FSCACHE_OBJECT_RELEASING] = "OBJECT_RELEASING", 30 [FSCACHE_OBJECT_RECYCLING] = "OBJECT_RECYCLING", 31 [FSCACHE_OBJECT_WITHDRAWING] = "OBJECT_WITHDRAWING", 32 [FSCACHE_OBJECT_DEAD] = "OBJECT_DEAD", 33}; 34EXPORT_SYMBOL(fscache_object_states); 35 36static void fscache_object_slow_work_put_ref(struct slow_work *); 37static int fscache_object_slow_work_get_ref(struct slow_work *); 38static void fscache_object_slow_work_execute(struct slow_work *); 39static void fscache_initialise_object(struct fscache_object *); 40static void fscache_lookup_object(struct fscache_object *); 41static void fscache_object_available(struct fscache_object *); 42static void fscache_release_object(struct fscache_object *); 43static void fscache_withdraw_object(struct fscache_object *); 44static void fscache_enqueue_dependents(struct fscache_object *); 45static void fscache_dequeue_object(struct fscache_object *); 46 47const struct slow_work_ops fscache_object_slow_work_ops = { 48 .get_ref = fscache_object_slow_work_get_ref, 49 .put_ref = fscache_object_slow_work_put_ref, 50 .execute = fscache_object_slow_work_execute, 51}; 52EXPORT_SYMBOL(fscache_object_slow_work_ops); 53 54/* 55 * we need to notify the parent when an op completes that we had outstanding 56 * upon it 57 */ 58static inline void fscache_done_parent_op(struct fscache_object *object) 59{ 60 struct fscache_object *parent = object->parent; 61 62 _enter("OBJ%x {OBJ%x,%x}", 63 object->debug_id, parent->debug_id, parent->n_ops); 64 65 spin_lock_nested(&parent->lock, 1); 66 parent->n_ops--; 67 parent->n_obj_ops--; 68 if (parent->n_ops == 0) 69 fscache_raise_event(parent, FSCACHE_OBJECT_EV_CLEARED); 70 spin_unlock(&parent->lock); 71} 72 73/* 74 * process events that have been sent to an object's state machine 75 * - initiates parent lookup 76 * - does object lookup 77 * - does object creation 78 * - does object recycling and retirement 79 * - does object withdrawal 80 */ 81static void fscache_object_state_machine(struct fscache_object *object) 82{ 83 enum fscache_object_state new_state; 84 85 ASSERT(object != NULL); 86 87 _enter("{OBJ%x,%s,%lx}", 88 object->debug_id, fscache_object_states[object->state], 89 object->events); 90 91 switch (object->state) { 92 /* wait for the parent object to become ready */ 93 case FSCACHE_OBJECT_INIT: 94 object->event_mask = 95 ULONG_MAX & ~(1 << FSCACHE_OBJECT_EV_CLEARED); 96 fscache_initialise_object(object); 97 goto done; 98 99 /* look up the object metadata on disk */ 100 case FSCACHE_OBJECT_LOOKING_UP: 101 fscache_lookup_object(object); 102 goto lookup_transit; 103 104 /* create the object metadata on disk */ 105 case FSCACHE_OBJECT_CREATING: 106 fscache_lookup_object(object); 107 goto lookup_transit; 108 109 /* handle an object becoming available; start pending 110 * operations and queue dependent operations for processing */ 111 case FSCACHE_OBJECT_AVAILABLE: 112 fscache_object_available(object); 113 goto active_transit; 114 115 /* normal running state */ 116 case FSCACHE_OBJECT_ACTIVE: 117 goto active_transit; 118 119 /* update the object metadata on disk */ 120 case FSCACHE_OBJECT_UPDATING: 121 clear_bit(FSCACHE_OBJECT_EV_UPDATE, &object->events); 122 fscache_stat(&fscache_n_updates_run); 123 object->cache->ops->update_object(object); 124 goto active_transit; 125 126 /* handle an object dying during lookup or creation */ 127 case FSCACHE_OBJECT_LC_DYING: 128 object->event_mask &= ~(1 << FSCACHE_OBJECT_EV_UPDATE); 129 object->cache->ops->lookup_complete(object); 130 131 spin_lock(&object->lock); 132 object->state = FSCACHE_OBJECT_DYING; 133 if (test_and_clear_bit(FSCACHE_COOKIE_CREATING, 134 &object->cookie->flags)) 135 wake_up_bit(&object->cookie->flags, 136 FSCACHE_COOKIE_CREATING); 137 spin_unlock(&object->lock); 138 139 fscache_done_parent_op(object); 140 141 /* wait for completion of all active operations on this object 142 * and the death of all child objects of this object */ 143 case FSCACHE_OBJECT_DYING: 144 dying: 145 clear_bit(FSCACHE_OBJECT_EV_CLEARED, &object->events); 146 spin_lock(&object->lock); 147 _debug("dying OBJ%x {%d,%d}", 148 object->debug_id, object->n_ops, object->n_children); 149 if (object->n_ops == 0 && object->n_children == 0) { 150 object->event_mask &= 151 ~(1 << FSCACHE_OBJECT_EV_CLEARED); 152 object->event_mask |= 153 (1 << FSCACHE_OBJECT_EV_WITHDRAW) | 154 (1 << FSCACHE_OBJECT_EV_RETIRE) | 155 (1 << FSCACHE_OBJECT_EV_RELEASE) | 156 (1 << FSCACHE_OBJECT_EV_ERROR); 157 } else { 158 object->event_mask &= 159 ~((1 << FSCACHE_OBJECT_EV_WITHDRAW) | 160 (1 << FSCACHE_OBJECT_EV_RETIRE) | 161 (1 << FSCACHE_OBJECT_EV_RELEASE) | 162 (1 << FSCACHE_OBJECT_EV_ERROR)); 163 object->event_mask |= 164 1 << FSCACHE_OBJECT_EV_CLEARED; 165 } 166 spin_unlock(&object->lock); 167 fscache_enqueue_dependents(object); 168 goto terminal_transit; 169 170 /* handle an abort during initialisation */ 171 case FSCACHE_OBJECT_ABORT_INIT: 172 _debug("handle abort init %lx", object->events); 173 object->event_mask &= ~(1 << FSCACHE_OBJECT_EV_UPDATE); 174 175 spin_lock(&object->lock); 176 fscache_dequeue_object(object); 177 178 object->state = FSCACHE_OBJECT_DYING; 179 if (test_and_clear_bit(FSCACHE_COOKIE_CREATING, 180 &object->cookie->flags)) 181 wake_up_bit(&object->cookie->flags, 182 FSCACHE_COOKIE_CREATING); 183 spin_unlock(&object->lock); 184 goto dying; 185 186 /* handle the netfs releasing an object and possibly marking it 187 * obsolete too */ 188 case FSCACHE_OBJECT_RELEASING: 189 case FSCACHE_OBJECT_RECYCLING: 190 object->event_mask &= 191 ~((1 << FSCACHE_OBJECT_EV_WITHDRAW) | 192 (1 << FSCACHE_OBJECT_EV_RETIRE) | 193 (1 << FSCACHE_OBJECT_EV_RELEASE) | 194 (1 << FSCACHE_OBJECT_EV_ERROR)); 195 fscache_release_object(object); 196 spin_lock(&object->lock); 197 object->state = FSCACHE_OBJECT_DEAD; 198 spin_unlock(&object->lock); 199 fscache_stat(&fscache_n_object_dead); 200 goto terminal_transit; 201 202 /* handle the parent cache of this object being withdrawn from 203 * active service */ 204 case FSCACHE_OBJECT_WITHDRAWING: 205 object->event_mask &= 206 ~((1 << FSCACHE_OBJECT_EV_WITHDRAW) | 207 (1 << FSCACHE_OBJECT_EV_RETIRE) | 208 (1 << FSCACHE_OBJECT_EV_RELEASE) | 209 (1 << FSCACHE_OBJECT_EV_ERROR)); 210 fscache_withdraw_object(object); 211 spin_lock(&object->lock); 212 object->state = FSCACHE_OBJECT_DEAD; 213 spin_unlock(&object->lock); 214 fscache_stat(&fscache_n_object_dead); 215 goto terminal_transit; 216 217 /* complain about the object being woken up once it is 218 * deceased */ 219 case FSCACHE_OBJECT_DEAD: 220 printk(KERN_ERR "FS-Cache:" 221 " Unexpected event in dead state %lx\n", 222 object->events & object->event_mask); 223 BUG(); 224 225 default: 226 printk(KERN_ERR "FS-Cache: Unknown object state %u\n", 227 object->state); 228 BUG(); 229 } 230 231 /* determine the transition from a lookup state */ 232lookup_transit: 233 switch (fls(object->events & object->event_mask) - 1) { 234 case FSCACHE_OBJECT_EV_WITHDRAW: 235 case FSCACHE_OBJECT_EV_RETIRE: 236 case FSCACHE_OBJECT_EV_RELEASE: 237 case FSCACHE_OBJECT_EV_ERROR: 238 new_state = FSCACHE_OBJECT_LC_DYING; 239 goto change_state; 240 case FSCACHE_OBJECT_EV_REQUEUE: 241 goto done; 242 case -1: 243 goto done; /* sleep until event */ 244 default: 245 goto unsupported_event; 246 } 247 248 /* determine the transition from an active state */ 249active_transit: 250 switch (fls(object->events & object->event_mask) - 1) { 251 case FSCACHE_OBJECT_EV_WITHDRAW: 252 case FSCACHE_OBJECT_EV_RETIRE: 253 case FSCACHE_OBJECT_EV_RELEASE: 254 case FSCACHE_OBJECT_EV_ERROR: 255 new_state = FSCACHE_OBJECT_DYING; 256 goto change_state; 257 case FSCACHE_OBJECT_EV_UPDATE: 258 new_state = FSCACHE_OBJECT_UPDATING; 259 goto change_state; 260 case -1: 261 new_state = FSCACHE_OBJECT_ACTIVE; 262 goto change_state; /* sleep until event */ 263 default: 264 goto unsupported_event; 265 } 266 267 /* determine the transition from a terminal state */ 268terminal_transit: 269 switch (fls(object->events & object->event_mask) - 1) { 270 case FSCACHE_OBJECT_EV_WITHDRAW: 271 new_state = FSCACHE_OBJECT_WITHDRAWING; 272 goto change_state; 273 case FSCACHE_OBJECT_EV_RETIRE: 274 new_state = FSCACHE_OBJECT_RECYCLING; 275 goto change_state; 276 case FSCACHE_OBJECT_EV_RELEASE: 277 new_state = FSCACHE_OBJECT_RELEASING; 278 goto change_state; 279 case FSCACHE_OBJECT_EV_ERROR: 280 new_state = FSCACHE_OBJECT_WITHDRAWING; 281 goto change_state; 282 case FSCACHE_OBJECT_EV_CLEARED: 283 new_state = FSCACHE_OBJECT_DYING; 284 goto change_state; 285 case -1: 286 goto done; /* sleep until event */ 287 default: 288 goto unsupported_event; 289 } 290 291change_state: 292 spin_lock(&object->lock); 293 object->state = new_state; 294 spin_unlock(&object->lock); 295 296done: 297 _leave(" [->%s]", fscache_object_states[object->state]); 298 return; 299 300unsupported_event: 301 printk(KERN_ERR "FS-Cache:" 302 " Unsupported event %lx [mask %lx] in state %s\n", 303 object->events, object->event_mask, 304 fscache_object_states[object->state]); 305 BUG(); 306} 307 308/* 309 * execute an object 310 */ 311static void fscache_object_slow_work_execute(struct slow_work *work) 312{ 313 struct fscache_object *object = 314 container_of(work, struct fscache_object, work); 315 unsigned long start; 316 317 _enter("{OBJ%x}", object->debug_id); 318 319 clear_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events); 320 321 start = jiffies; 322 fscache_object_state_machine(object); 323 fscache_hist(fscache_objs_histogram, start); 324 if (object->events & object->event_mask) 325 fscache_enqueue_object(object); 326} 327 328/* 329 * initialise an object 330 * - check the specified object's parent to see if we can make use of it 331 * immediately to do a creation 332 * - we may need to start the process of creating a parent and we need to wait 333 * for the parent's lookup and creation to complete if it's not there yet 334 * - an object's cookie is pinned until we clear FSCACHE_COOKIE_CREATING on the 335 * leaf-most cookies of the object and all its children 336 */ 337static void fscache_initialise_object(struct fscache_object *object) 338{ 339 struct fscache_object *parent; 340 341 _enter(""); 342 ASSERT(object->cookie != NULL); 343 ASSERT(object->cookie->parent != NULL); 344 ASSERT(list_empty(&object->work.link)); 345 346 if (object->events & ((1 << FSCACHE_OBJECT_EV_ERROR) | 347 (1 << FSCACHE_OBJECT_EV_RELEASE) | 348 (1 << FSCACHE_OBJECT_EV_RETIRE) | 349 (1 << FSCACHE_OBJECT_EV_WITHDRAW))) { 350 _debug("abort init %lx", object->events); 351 spin_lock(&object->lock); 352 object->state = FSCACHE_OBJECT_ABORT_INIT; 353 spin_unlock(&object->lock); 354 return; 355 } 356 357 spin_lock(&object->cookie->lock); 358 spin_lock_nested(&object->cookie->parent->lock, 1); 359 360 parent = object->parent; 361 if (!parent) { 362 _debug("no parent"); 363 set_bit(FSCACHE_OBJECT_EV_WITHDRAW, &object->events); 364 } else { 365 spin_lock(&object->lock); 366 spin_lock_nested(&parent->lock, 1); 367 _debug("parent %s", fscache_object_states[parent->state]); 368 369 if (parent->state >= FSCACHE_OBJECT_DYING) { 370 _debug("bad parent"); 371 set_bit(FSCACHE_OBJECT_EV_WITHDRAW, &object->events); 372 } else if (parent->state < FSCACHE_OBJECT_AVAILABLE) { 373 _debug("wait"); 374 375 /* we may get woken up in this state by child objects 376 * binding on to us, so we need to make sure we don't 377 * add ourself to the list multiple times */ 378 if (list_empty(&object->dep_link)) { 379 object->cache->ops->grab_object(object); 380 list_add(&object->dep_link, 381 &parent->dependents); 382 383 /* fscache_acquire_non_index_cookie() uses this 384 * to wake the chain up */ 385 if (parent->state == FSCACHE_OBJECT_INIT) 386 fscache_enqueue_object(parent); 387 } 388 } else { 389 _debug("go"); 390 parent->n_ops++; 391 parent->n_obj_ops++; 392 object->lookup_jif = jiffies; 393 object->state = FSCACHE_OBJECT_LOOKING_UP; 394 set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events); 395 } 396 397 spin_unlock(&parent->lock); 398 spin_unlock(&object->lock); 399 } 400 401 spin_unlock(&object->cookie->parent->lock); 402 spin_unlock(&object->cookie->lock); 403 _leave(""); 404} 405 406/* 407 * look an object up in the cache from which it was allocated 408 * - we hold an "access lock" on the parent object, so the parent object cannot 409 * be withdrawn by either party till we've finished 410 * - an object's cookie is pinned until we clear FSCACHE_COOKIE_CREATING on the 411 * leaf-most cookies of the object and all its children 412 */ 413static void fscache_lookup_object(struct fscache_object *object) 414{ 415 struct fscache_cookie *cookie = object->cookie; 416 struct fscache_object *parent; 417 418 _enter(""); 419 420 parent = object->parent; 421 ASSERT(parent != NULL); 422 ASSERTCMP(parent->n_ops, >, 0); 423 ASSERTCMP(parent->n_obj_ops, >, 0); 424 425 /* make sure the parent is still available */ 426 ASSERTCMP(parent->state, >=, FSCACHE_OBJECT_AVAILABLE); 427 428 if (parent->state >= FSCACHE_OBJECT_DYING || 429 test_bit(FSCACHE_IOERROR, &object->cache->flags)) { 430 _debug("unavailable"); 431 set_bit(FSCACHE_OBJECT_EV_WITHDRAW, &object->events); 432 _leave(""); 433 return; 434 } 435 436 _debug("LOOKUP \"%s/%s\" in \"%s\"", 437 parent->cookie->def->name, cookie->def->name, 438 object->cache->tag->name); 439 440 fscache_stat(&fscache_n_object_lookups); 441 object->cache->ops->lookup_object(object); 442 443 if (test_bit(FSCACHE_OBJECT_EV_ERROR, &object->events)) 444 set_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags); 445 446 _leave(""); 447} 448 449/** 450 * fscache_object_lookup_negative - Note negative cookie lookup 451 * @object: Object pointing to cookie to mark 452 * 453 * Note negative lookup, permitting those waiting to read data from an already 454 * existing backing object to continue as there's no data for them to read. 455 */ 456void fscache_object_lookup_negative(struct fscache_object *object) 457{ 458 struct fscache_cookie *cookie = object->cookie; 459 460 _enter("{OBJ%x,%s}", 461 object->debug_id, fscache_object_states[object->state]); 462 463 spin_lock(&object->lock); 464 if (object->state == FSCACHE_OBJECT_LOOKING_UP) { 465 fscache_stat(&fscache_n_object_lookups_negative); 466 467 /* transit here to allow write requests to begin stacking up 468 * and read requests to begin returning ENODATA */ 469 object->state = FSCACHE_OBJECT_CREATING; 470 spin_unlock(&object->lock); 471 472 set_bit(FSCACHE_COOKIE_PENDING_FILL, &cookie->flags); 473 set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags); 474 475 _debug("wake up lookup %p", &cookie->flags); 476 smp_mb__before_clear_bit(); 477 clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags); 478 smp_mb__after_clear_bit(); 479 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP); 480 set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events); 481 } else { 482 ASSERTCMP(object->state, ==, FSCACHE_OBJECT_CREATING); 483 spin_unlock(&object->lock); 484 } 485 486 _leave(""); 487} 488EXPORT_SYMBOL(fscache_object_lookup_negative); 489 490/** 491 * fscache_obtained_object - Note successful object lookup or creation 492 * @object: Object pointing to cookie to mark 493 * 494 * Note successful lookup and/or creation, permitting those waiting to write 495 * data to a backing object to continue. 496 * 497 * Note that after calling this, an object's cookie may be relinquished by the 498 * netfs, and so must be accessed with object lock held. 499 */ 500void fscache_obtained_object(struct fscache_object *object) 501{ 502 struct fscache_cookie *cookie = object->cookie; 503 504 _enter("{OBJ%x,%s}", 505 object->debug_id, fscache_object_states[object->state]); 506 507 /* if we were still looking up, then we must have a positive lookup 508 * result, in which case there may be data available */ 509 spin_lock(&object->lock); 510 if (object->state == FSCACHE_OBJECT_LOOKING_UP) { 511 fscache_stat(&fscache_n_object_lookups_positive); 512 513 clear_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags); 514 515 object->state = FSCACHE_OBJECT_AVAILABLE; 516 spin_unlock(&object->lock); 517 518 smp_mb__before_clear_bit(); 519 clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags); 520 smp_mb__after_clear_bit(); 521 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP); 522 set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events); 523 } else { 524 ASSERTCMP(object->state, ==, FSCACHE_OBJECT_CREATING); 525 fscache_stat(&fscache_n_object_created); 526 527 object->state = FSCACHE_OBJECT_AVAILABLE; 528 spin_unlock(&object->lock); 529 set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events); 530 smp_wmb(); 531 } 532 533 if (test_and_clear_bit(FSCACHE_COOKIE_CREATING, &cookie->flags)) 534 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_CREATING); 535 536 _leave(""); 537} 538EXPORT_SYMBOL(fscache_obtained_object); 539 540/* 541 * handle an object that has just become available 542 */ 543static void fscache_object_available(struct fscache_object *object) 544{ 545 _enter("{OBJ%x}", object->debug_id); 546 547 spin_lock(&object->lock); 548 549 if (test_and_clear_bit(FSCACHE_COOKIE_CREATING, &object->cookie->flags)) 550 wake_up_bit(&object->cookie->flags, FSCACHE_COOKIE_CREATING); 551 552 fscache_done_parent_op(object); 553 if (object->n_in_progress == 0) { 554 if (object->n_ops > 0) { 555 ASSERTCMP(object->n_ops, >=, object->n_obj_ops); 556 ASSERTIF(object->n_ops > object->n_obj_ops, 557 !list_empty(&object->pending_ops)); 558 fscache_start_operations(object); 559 } else { 560 ASSERT(list_empty(&object->pending_ops)); 561 } 562 } 563 spin_unlock(&object->lock); 564 565 object->cache->ops->lookup_complete(object); 566 fscache_enqueue_dependents(object); 567 568 fscache_hist(fscache_obj_instantiate_histogram, object->lookup_jif); 569 fscache_stat(&fscache_n_object_avail); 570 571 _leave(""); 572} 573 574/* 575 * drop an object's attachments 576 */ 577static void fscache_drop_object(struct fscache_object *object) 578{ 579 struct fscache_object *parent = object->parent; 580 struct fscache_cache *cache = object->cache; 581 582 _enter("{OBJ%x,%d}", object->debug_id, object->n_children); 583 584 spin_lock(&cache->object_list_lock); 585 list_del_init(&object->cache_link); 586 spin_unlock(&cache->object_list_lock); 587 588 cache->ops->drop_object(object); 589 590 if (parent) { 591 _debug("release parent OBJ%x {%d}", 592 parent->debug_id, parent->n_children); 593 594 spin_lock(&parent->lock); 595 parent->n_children--; 596 if (parent->n_children == 0) 597 fscache_raise_event(parent, FSCACHE_OBJECT_EV_CLEARED); 598 spin_unlock(&parent->lock); 599 object->parent = NULL; 600 } 601 602 /* this just shifts the object release to the slow work processor */ 603 object->cache->ops->put_object(object); 604 605 _leave(""); 606} 607 608/* 609 * release or recycle an object that the netfs has discarded 610 */ 611static void fscache_release_object(struct fscache_object *object) 612{ 613 _enter(""); 614 615 fscache_drop_object(object); 616} 617 618/* 619 * withdraw an object from active service 620 */ 621static void fscache_withdraw_object(struct fscache_object *object) 622{ 623 struct fscache_cookie *cookie; 624 bool detached; 625 626 _enter(""); 627 628 spin_lock(&object->lock); 629 cookie = object->cookie; 630 if (cookie) { 631 /* need to get the cookie lock before the object lock, starting 632 * from the object pointer */ 633 atomic_inc(&cookie->usage); 634 spin_unlock(&object->lock); 635 636 detached = false; 637 spin_lock(&cookie->lock); 638 spin_lock(&object->lock); 639 640 if (object->cookie == cookie) { 641 hlist_del_init(&object->cookie_link); 642 object->cookie = NULL; 643 detached = true; 644 } 645 spin_unlock(&cookie->lock); 646 fscache_cookie_put(cookie); 647 if (detached) 648 fscache_cookie_put(cookie); 649 } 650 651 spin_unlock(&object->lock); 652 653 fscache_drop_object(object); 654} 655 656/* 657 * withdraw an object from active service at the behest of the cache 658 * - need break the links to a cached object cookie 659 * - called under two situations: 660 * (1) recycler decides to reclaim an in-use object 661 * (2) a cache is unmounted 662 * - have to take care as the cookie can be being relinquished by the netfs 663 * simultaneously 664 * - the object is pinned by the caller holding a refcount on it 665 */ 666void fscache_withdrawing_object(struct fscache_cache *cache, 667 struct fscache_object *object) 668{ 669 bool enqueue = false; 670 671 _enter(",OBJ%x", object->debug_id); 672 673 spin_lock(&object->lock); 674 if (object->state < FSCACHE_OBJECT_WITHDRAWING) { 675 object->state = FSCACHE_OBJECT_WITHDRAWING; 676 enqueue = true; 677 } 678 spin_unlock(&object->lock); 679 680 if (enqueue) 681 fscache_enqueue_object(object); 682 683 _leave(""); 684} 685 686/* 687 * allow the slow work item processor to get a ref on an object 688 */ 689static int fscache_object_slow_work_get_ref(struct slow_work *work) 690{ 691 struct fscache_object *object = 692 container_of(work, struct fscache_object, work); 693 694 return object->cache->ops->grab_object(object) ? 0 : -EAGAIN; 695} 696 697/* 698 * allow the slow work item processor to discard a ref on a work item 699 */ 700static void fscache_object_slow_work_put_ref(struct slow_work *work) 701{ 702 struct fscache_object *object = 703 container_of(work, struct fscache_object, work); 704 705 return object->cache->ops->put_object(object); 706} 707 708/* 709 * enqueue an object for metadata-type processing 710 */ 711void fscache_enqueue_object(struct fscache_object *object) 712{ 713 _enter("{OBJ%x}", object->debug_id); 714 715 slow_work_enqueue(&object->work); 716} 717 718/* 719 * enqueue the dependents of an object for metadata-type processing 720 * - the caller must hold the object's lock 721 * - this may cause an already locked object to wind up being processed again 722 */ 723static void fscache_enqueue_dependents(struct fscache_object *object) 724{ 725 struct fscache_object *dep; 726 727 _enter("{OBJ%x}", object->debug_id); 728 729 if (list_empty(&object->dependents)) 730 return; 731 732 spin_lock(&object->lock); 733 734 while (!list_empty(&object->dependents)) { 735 dep = list_entry(object->dependents.next, 736 struct fscache_object, dep_link); 737 list_del_init(&dep->dep_link); 738 739 740 /* sort onto appropriate lists */ 741 fscache_enqueue_object(dep); 742 dep->cache->ops->put_object(dep); 743 744 if (!list_empty(&object->dependents)) 745 cond_resched_lock(&object->lock); 746 } 747 748 spin_unlock(&object->lock); 749} 750 751/* 752 * remove an object from whatever queue it's waiting on 753 * - the caller must hold object->lock 754 */ 755void fscache_dequeue_object(struct fscache_object *object) 756{ 757 _enter("{OBJ%x}", object->debug_id); 758 759 if (!list_empty(&object->dep_link)) { 760 spin_lock(&object->parent->lock); 761 list_del_init(&object->dep_link); 762 spin_unlock(&object->parent->lock); 763 } 764 765 _leave(""); 766} 767 768/** 769 * fscache_check_aux - Ask the netfs whether an object on disk is still valid 770 * @object: The object to ask about 771 * @data: The auxiliary data for the object 772 * @datalen: The size of the auxiliary data 773 * 774 * This function consults the netfs about the coherency state of an object 775 */ 776enum fscache_checkaux fscache_check_aux(struct fscache_object *object, 777 const void *data, uint16_t datalen) 778{ 779 enum fscache_checkaux result; 780 781 if (!object->cookie->def->check_aux) { 782 fscache_stat(&fscache_n_checkaux_none); 783 return FSCACHE_CHECKAUX_OKAY; 784 } 785 786 result = object->cookie->def->check_aux(object->cookie->netfs_data, 787 data, datalen); 788 switch (result) { 789 /* entry okay as is */ 790 case FSCACHE_CHECKAUX_OKAY: 791 fscache_stat(&fscache_n_checkaux_okay); 792 break; 793 794 /* entry requires update */ 795 case FSCACHE_CHECKAUX_NEEDS_UPDATE: 796 fscache_stat(&fscache_n_checkaux_update); 797 break; 798 799 /* entry requires deletion */ 800 case FSCACHE_CHECKAUX_OBSOLETE: 801 fscache_stat(&fscache_n_checkaux_obsolete); 802 break; 803 804 default: 805 BUG(); 806 } 807 808 return result; 809} 810EXPORT_SYMBOL(fscache_check_aux);