xfs_behavior.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
  3. * All Rights Reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it would be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write the Free Software Foundation,
  16. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include "xfs.h"
  19. /*
  20. * Source file used to associate/disassociate behaviors with virtualized
  21. * objects. See xfs_behavior.h for more information about behaviors, etc.
  22. *
  23. * The implementation is split between functions in this file and macros
  24. * in xfs_behavior.h.
  25. */
  26. /*
  27. * Insert a new behavior descriptor into a behavior chain.
  28. *
  29. * The behavior chain is ordered based on the 'position' number which
  30. * lives in the first field of the ops vector (higher numbers first).
  31. *
  32. * Attempts to insert duplicate ops result in an EINVAL return code.
  33. * Otherwise, return 0 to indicate success.
  34. */
  35. int
  36. bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp)
  37. {
  38. bhv_desc_t *curdesc, *prev;
  39. int position;
  40. /*
  41. * Validate the position value of the new behavior.
  42. */
  43. position = BHV_POSITION(bdp);
  44. ASSERT(position >= BHV_POSITION_BASE && position <= BHV_POSITION_TOP);
  45. /*
  46. * Find location to insert behavior. Check for duplicates.
  47. */
  48. prev = NULL;
  49. for (curdesc = bhp->bh_first;
  50. curdesc != NULL;
  51. curdesc = curdesc->bd_next) {
  52. /* Check for duplication. */
  53. if (curdesc->bd_ops == bdp->bd_ops) {
  54. ASSERT(0);
  55. return EINVAL;
  56. }
  57. /* Find correct position */
  58. if (position >= BHV_POSITION(curdesc)) {
  59. ASSERT(position != BHV_POSITION(curdesc));
  60. break; /* found it */
  61. }
  62. prev = curdesc;
  63. }
  64. if (prev == NULL) {
  65. /* insert at front of chain */
  66. bdp->bd_next = bhp->bh_first;
  67. bhp->bh_first = bdp;
  68. } else {
  69. /* insert after prev */
  70. bdp->bd_next = prev->bd_next;
  71. prev->bd_next = bdp;
  72. }
  73. return 0;
  74. }
  75. /*
  76. * Remove a behavior descriptor from a position in a behavior chain;
  77. * the position is guaranteed not to be the first position.
  78. * Should only be called by the bhv_remove() macro.
  79. */
  80. void
  81. bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp)
  82. {
  83. bhv_desc_t *curdesc, *prev;
  84. ASSERT(bhp->bh_first != NULL);
  85. ASSERT(bhp->bh_first->bd_next != NULL);
  86. prev = bhp->bh_first;
  87. for (curdesc = bhp->bh_first->bd_next;
  88. curdesc != NULL;
  89. curdesc = curdesc->bd_next) {
  90. if (curdesc == bdp)
  91. break; /* found it */
  92. prev = curdesc;
  93. }
  94. ASSERT(curdesc == bdp);
  95. prev->bd_next = bdp->bd_next; /* remove from after prev */
  96. }
  97. /*
  98. * Looks for the first behavior within a specified range of positions.
  99. * Return the associated behavior descriptor. Or NULL, if none found.
  100. */
  101. bhv_desc_t *
  102. bhv_lookup_range(bhv_head_t *bhp, int low, int high)
  103. {
  104. bhv_desc_t *curdesc;
  105. for (curdesc = bhp->bh_first;
  106. curdesc != NULL;
  107. curdesc = curdesc->bd_next) {
  108. int position = BHV_POSITION(curdesc);
  109. if (position <= high) {
  110. if (position >= low)
  111. return curdesc;
  112. return NULL;
  113. }
  114. }
  115. return NULL;
  116. }
  117. /*
  118. * Return the base behavior in the chain, or NULL if the chain
  119. * is empty.
  120. *
  121. * The caller has not read locked the behavior chain, so acquire the
  122. * lock before traversing the chain.
  123. */
  124. bhv_desc_t *
  125. bhv_base(bhv_head_t *bhp)
  126. {
  127. bhv_desc_t *curdesc;
  128. for (curdesc = bhp->bh_first;
  129. curdesc != NULL;
  130. curdesc = curdesc->bd_next) {
  131. if (curdesc->bd_next == NULL) {
  132. return curdesc;
  133. }
  134. }
  135. return NULL;
  136. }
  137. void
  138. bhv_head_init(
  139. bhv_head_t *bhp,
  140. char *name)
  141. {
  142. bhp->bh_first = NULL;
  143. }
  144. void
  145. bhv_insert_initial(
  146. bhv_head_t *bhp,
  147. bhv_desc_t *bdp)
  148. {
  149. ASSERT(bhp->bh_first == NULL);
  150. (bhp)->bh_first = bdp;
  151. }
  152. void
  153. bhv_head_destroy(
  154. bhv_head_t *bhp)
  155. {
  156. ASSERT(bhp->bh_first == NULL);
  157. }