list_lru.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*
  2. * Copyright (c) 2013 Red Hat, Inc. and Parallels Inc. All rights reserved.
  3. * Authors: David Chinner and Glauber Costa
  4. *
  5. * Generic LRU infrastructure
  6. */
  7. #include <linux/kernel.h>
  8. #include <linux/module.h>
  9. #include <linux/list_lru.h>
  10. bool list_lru_add(struct list_lru *lru, struct list_head *item)
  11. {
  12. spin_lock(&lru->lock);
  13. if (list_empty(item)) {
  14. list_add_tail(item, &lru->list);
  15. lru->nr_items++;
  16. spin_unlock(&lru->lock);
  17. return true;
  18. }
  19. spin_unlock(&lru->lock);
  20. return false;
  21. }
  22. EXPORT_SYMBOL_GPL(list_lru_add);
  23. bool list_lru_del(struct list_lru *lru, struct list_head *item)
  24. {
  25. spin_lock(&lru->lock);
  26. if (!list_empty(item)) {
  27. list_del_init(item);
  28. lru->nr_items--;
  29. spin_unlock(&lru->lock);
  30. return true;
  31. }
  32. spin_unlock(&lru->lock);
  33. return false;
  34. }
  35. EXPORT_SYMBOL_GPL(list_lru_del);
  36. unsigned long list_lru_walk(struct list_lru *lru, list_lru_walk_cb isolate,
  37. void *cb_arg, unsigned long nr_to_walk)
  38. {
  39. struct list_head *item, *n;
  40. unsigned long removed = 0;
  41. /*
  42. * If we don't keep state of at which pass we are, we can loop at
  43. * LRU_RETRY, since we have no guarantees that the caller will be able
  44. * to do something other than retry on the next pass. We handle this by
  45. * allowing at most one retry per object. This should not be altered
  46. * by any condition other than LRU_RETRY.
  47. */
  48. bool first_pass = true;
  49. spin_lock(&lru->lock);
  50. restart:
  51. list_for_each_safe(item, n, &lru->list) {
  52. enum lru_status ret;
  53. ret = isolate(item, &lru->lock, cb_arg);
  54. switch (ret) {
  55. case LRU_REMOVED:
  56. lru->nr_items--;
  57. removed++;
  58. break;
  59. case LRU_ROTATE:
  60. list_move_tail(item, &lru->list);
  61. break;
  62. case LRU_SKIP:
  63. break;
  64. case LRU_RETRY:
  65. if (!first_pass) {
  66. first_pass = true;
  67. break;
  68. }
  69. first_pass = false;
  70. goto restart;
  71. default:
  72. BUG();
  73. }
  74. if (nr_to_walk-- == 0)
  75. break;
  76. }
  77. spin_unlock(&lru->lock);
  78. return removed;
  79. }
  80. EXPORT_SYMBOL_GPL(list_lru_walk);
  81. unsigned long list_lru_dispose_all(struct list_lru *lru,
  82. list_lru_dispose_cb dispose)
  83. {
  84. unsigned long disposed = 0;
  85. LIST_HEAD(dispose_list);
  86. spin_lock(&lru->lock);
  87. while (!list_empty(&lru->list)) {
  88. list_splice_init(&lru->list, &dispose_list);
  89. disposed += lru->nr_items;
  90. lru->nr_items = 0;
  91. spin_unlock(&lru->lock);
  92. dispose(&dispose_list);
  93. spin_lock(&lru->lock);
  94. }
  95. spin_unlock(&lru->lock);
  96. return disposed;
  97. }
  98. int list_lru_init(struct list_lru *lru)
  99. {
  100. spin_lock_init(&lru->lock);
  101. INIT_LIST_HEAD(&lru->list);
  102. lru->nr_items = 0;
  103. return 0;
  104. }
  105. EXPORT_SYMBOL_GPL(list_lru_init);