zfcp_reqlist.h 5.4 KB

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