zfcp_reqlist.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * zfcp device driver
  4. *
  5. * Data structure and helper functions for tracking pending FSF
  6. * requests.
  7. *
  8. * Copyright IBM Corp. 2009, 2016
  9. */
  10. #ifndef ZFCP_REQLIST_H
  11. #define ZFCP_REQLIST_H
  12. /* number of hash buckets */
  13. #define ZFCP_REQ_LIST_BUCKETS 128
  14. /**
  15. * struct zfcp_reqlist - Container for request list (reqlist)
  16. * @lock: Spinlock for protecting the hash list
  17. * @buckets: Array of hashbuckets, each is a list of requests in this bucket
  18. */
  19. struct zfcp_reqlist {
  20. spinlock_t lock;
  21. struct list_head buckets[ZFCP_REQ_LIST_BUCKETS];
  22. };
  23. static inline int zfcp_reqlist_hash(unsigned long req_id)
  24. {
  25. return req_id % ZFCP_REQ_LIST_BUCKETS;
  26. }
  27. /**
  28. * zfcp_reqlist_alloc - Allocate and initialize reqlist
  29. *
  30. * Returns pointer to allocated reqlist on success, or NULL on
  31. * allocation failure.
  32. */
  33. static inline struct zfcp_reqlist *zfcp_reqlist_alloc(void)
  34. {
  35. unsigned int i;
  36. struct zfcp_reqlist *rl;
  37. rl = kzalloc(sizeof(struct zfcp_reqlist), GFP_KERNEL);
  38. if (!rl)
  39. return NULL;
  40. spin_lock_init(&rl->lock);
  41. for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
  42. INIT_LIST_HEAD(&rl->buckets[i]);
  43. return rl;
  44. }
  45. /**
  46. * zfcp_reqlist_isempty - Check whether the request list empty
  47. * @rl: pointer to reqlist
  48. *
  49. * Returns: 1 if list is empty, 0 if not
  50. */
  51. static inline int zfcp_reqlist_isempty(struct zfcp_reqlist *rl)
  52. {
  53. unsigned int i;
  54. for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
  55. if (!list_empty(&rl->buckets[i]))
  56. return 0;
  57. return 1;
  58. }
  59. /**
  60. * zfcp_reqlist_free - Free allocated memory for reqlist
  61. * @rl: The reqlist where to free memory
  62. */
  63. static inline void zfcp_reqlist_free(struct zfcp_reqlist *rl)
  64. {
  65. /* sanity check */
  66. BUG_ON(!zfcp_reqlist_isempty(rl));
  67. kfree(rl);
  68. }
  69. static inline struct zfcp_fsf_req *
  70. _zfcp_reqlist_find(struct zfcp_reqlist *rl, unsigned long req_id)
  71. {
  72. struct zfcp_fsf_req *req;
  73. unsigned int i;
  74. i = zfcp_reqlist_hash(req_id);
  75. list_for_each_entry(req, &rl->buckets[i], list)
  76. if (req->req_id == req_id)
  77. return req;
  78. return NULL;
  79. }
  80. /**
  81. * zfcp_reqlist_find - Lookup FSF request by its request id
  82. * @rl: The reqlist where to lookup the FSF request
  83. * @req_id: The request id to look for
  84. *
  85. * Returns a pointer to the FSF request with the specified request id
  86. * or NULL if there is no known FSF request with this id.
  87. */
  88. static inline struct zfcp_fsf_req *
  89. zfcp_reqlist_find(struct zfcp_reqlist *rl, unsigned long req_id)
  90. {
  91. unsigned long flags;
  92. struct zfcp_fsf_req *req;
  93. spin_lock_irqsave(&rl->lock, flags);
  94. req = _zfcp_reqlist_find(rl, req_id);
  95. spin_unlock_irqrestore(&rl->lock, flags);
  96. return req;
  97. }
  98. /**
  99. * zfcp_reqlist_find_rm - Lookup request by id and remove it from reqlist
  100. * @rl: reqlist where to search and remove entry
  101. * @req_id: The request id of the request to look for
  102. *
  103. * This functions tries to find the FSF request with the specified
  104. * id and then removes it from the reqlist. The reqlist lock is held
  105. * during both steps of the operation.
  106. *
  107. * Returns: Pointer to the FSF request if the request has been found,
  108. * NULL if it has not been found.
  109. */
  110. static inline struct zfcp_fsf_req *
  111. zfcp_reqlist_find_rm(struct zfcp_reqlist *rl, unsigned long req_id)
  112. {
  113. unsigned long flags;
  114. struct zfcp_fsf_req *req;
  115. spin_lock_irqsave(&rl->lock, flags);
  116. req = _zfcp_reqlist_find(rl, req_id);
  117. if (req)
  118. list_del(&req->list);
  119. spin_unlock_irqrestore(&rl->lock, flags);
  120. return req;
  121. }
  122. /**
  123. * zfcp_reqlist_add - Add entry to reqlist
  124. * @rl: reqlist where to add the entry
  125. * @req: The entry to add
  126. *
  127. * The request id always increases. As an optimization new requests
  128. * are added here with list_add_tail at the end of the bucket lists
  129. * while old requests are looked up starting at the beginning of the
  130. * lists.
  131. */
  132. static inline void zfcp_reqlist_add(struct zfcp_reqlist *rl,
  133. struct zfcp_fsf_req *req)
  134. {
  135. unsigned int i;
  136. unsigned long flags;
  137. i = zfcp_reqlist_hash(req->req_id);
  138. spin_lock_irqsave(&rl->lock, flags);
  139. list_add_tail(&req->list, &rl->buckets[i]);
  140. spin_unlock_irqrestore(&rl->lock, flags);
  141. }
  142. /**
  143. * zfcp_reqlist_move - Move all entries from reqlist to simple list
  144. * @rl: The zfcp_reqlist where to remove all entries
  145. * @list: The list where to move all entries
  146. */
  147. static inline void zfcp_reqlist_move(struct zfcp_reqlist *rl,
  148. struct list_head *list)
  149. {
  150. unsigned int i;
  151. unsigned long flags;
  152. spin_lock_irqsave(&rl->lock, flags);
  153. for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
  154. list_splice_init(&rl->buckets[i], list);
  155. spin_unlock_irqrestore(&rl->lock, flags);
  156. }
  157. /**
  158. * zfcp_reqlist_apply_for_all() - apply a function to every request.
  159. * @rl: the requestlist that contains the target requests.
  160. * @f: the function to apply to each request; the first parameter of the
  161. * function will be the target-request; the second parameter is the same
  162. * pointer as given with the argument @data.
  163. * @data: freely chosen argument; passed through to @f as second parameter.
  164. *
  165. * Uses :c:macro:`list_for_each_entry` to iterate over the lists in the hash-
  166. * table (not a 'safe' variant, so don't modify the list).
  167. *
  168. * Holds @rl->lock over the entire request-iteration.
  169. */
  170. static inline void
  171. zfcp_reqlist_apply_for_all(struct zfcp_reqlist *rl,
  172. void (*f)(struct zfcp_fsf_req *, void *), void *data)
  173. {
  174. struct zfcp_fsf_req *req;
  175. unsigned long flags;
  176. unsigned int i;
  177. spin_lock_irqsave(&rl->lock, flags);
  178. for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
  179. list_for_each_entry(req, &rl->buckets[i], list)
  180. f(req, data);
  181. spin_unlock_irqrestore(&rl->lock, flags);
  182. }
  183. #endif /* ZFCP_REQLIST_H */