1 /* SPDX-License-Identifier: GPL-2.0 */
5 * Data structure and helper functions for tracking pending FSF
8 * Copyright IBM Corp. 2009, 2023
11 #ifndef ZFCP_REQLIST_H
12 #define ZFCP_REQLIST_H
14 #include <linux/types.h>
16 /* number of hash buckets */
17 #define ZFCP_REQ_LIST_BUCKETS 128u
20 * struct zfcp_reqlist - Container for request list (reqlist)
21 * @lock: Spinlock for protecting the hash list
22 * @buckets: Array of hashbuckets, each is a list of requests in this bucket
26 struct list_head buckets
[ZFCP_REQ_LIST_BUCKETS
];
29 static inline size_t zfcp_reqlist_hash(u64 req_id
)
31 return req_id
% ZFCP_REQ_LIST_BUCKETS
;
35 * zfcp_reqlist_alloc - Allocate and initialize reqlist
37 * Returns pointer to allocated reqlist on success, or NULL on
40 static inline struct zfcp_reqlist
*zfcp_reqlist_alloc(void)
43 struct zfcp_reqlist
*rl
;
45 rl
= kzalloc(sizeof(struct zfcp_reqlist
), GFP_KERNEL
);
49 spin_lock_init(&rl
->lock
);
51 for (i
= 0; i
< ZFCP_REQ_LIST_BUCKETS
; i
++)
52 INIT_LIST_HEAD(&rl
->buckets
[i
]);
58 * zfcp_reqlist_isempty - Check whether the request list empty
59 * @rl: pointer to reqlist
61 * Returns: 1 if list is empty, 0 if not
63 static inline int zfcp_reqlist_isempty(struct zfcp_reqlist
*rl
)
67 for (i
= 0; i
< ZFCP_REQ_LIST_BUCKETS
; i
++)
68 if (!list_empty(&rl
->buckets
[i
]))
74 * zfcp_reqlist_free - Free allocated memory for reqlist
75 * @rl: The reqlist where to free memory
77 static inline void zfcp_reqlist_free(struct zfcp_reqlist
*rl
)
80 BUG_ON(!zfcp_reqlist_isempty(rl
));
85 static inline struct zfcp_fsf_req
*
86 _zfcp_reqlist_find(struct zfcp_reqlist
*rl
, u64 req_id
)
88 struct zfcp_fsf_req
*req
;
91 i
= zfcp_reqlist_hash(req_id
);
92 list_for_each_entry(req
, &rl
->buckets
[i
], list
)
93 if (req
->req_id
== req_id
)
99 * zfcp_reqlist_find - Lookup FSF request by its request id
100 * @rl: The reqlist where to lookup the FSF request
101 * @req_id: The request id to look for
103 * Returns a pointer to the FSF request with the specified request id
104 * or NULL if there is no known FSF request with this id.
106 static inline struct zfcp_fsf_req
*
107 zfcp_reqlist_find(struct zfcp_reqlist
*rl
, u64 req_id
)
110 struct zfcp_fsf_req
*req
;
112 spin_lock_irqsave(&rl
->lock
, flags
);
113 req
= _zfcp_reqlist_find(rl
, req_id
);
114 spin_unlock_irqrestore(&rl
->lock
, flags
);
120 * zfcp_reqlist_find_rm - Lookup request by id and remove it from reqlist
121 * @rl: reqlist where to search and remove entry
122 * @req_id: The request id of the request to look for
124 * This functions tries to find the FSF request with the specified
125 * id and then removes it from the reqlist. The reqlist lock is held
126 * during both steps of the operation.
128 * Returns: Pointer to the FSF request if the request has been found,
129 * NULL if it has not been found.
131 static inline struct zfcp_fsf_req
*
132 zfcp_reqlist_find_rm(struct zfcp_reqlist
*rl
, u64 req_id
)
135 struct zfcp_fsf_req
*req
;
137 spin_lock_irqsave(&rl
->lock
, flags
);
138 req
= _zfcp_reqlist_find(rl
, req_id
);
140 list_del(&req
->list
);
141 spin_unlock_irqrestore(&rl
->lock
, flags
);
147 * zfcp_reqlist_add - Add entry to reqlist
148 * @rl: reqlist where to add the entry
149 * @req: The entry to add
151 * The request id always increases. As an optimization new requests
152 * are added here with list_add_tail at the end of the bucket lists
153 * while old requests are looked up starting at the beginning of the
156 static inline void zfcp_reqlist_add(struct zfcp_reqlist
*rl
,
157 struct zfcp_fsf_req
*req
)
162 i
= zfcp_reqlist_hash(req
->req_id
);
164 spin_lock_irqsave(&rl
->lock
, flags
);
165 list_add_tail(&req
->list
, &rl
->buckets
[i
]);
166 spin_unlock_irqrestore(&rl
->lock
, flags
);
170 * zfcp_reqlist_move - Move all entries from reqlist to simple list
171 * @rl: The zfcp_reqlist where to remove all entries
172 * @list: The list where to move all entries
174 static inline void zfcp_reqlist_move(struct zfcp_reqlist
*rl
,
175 struct list_head
*list
)
180 spin_lock_irqsave(&rl
->lock
, flags
);
181 for (i
= 0; i
< ZFCP_REQ_LIST_BUCKETS
; i
++)
182 list_splice_init(&rl
->buckets
[i
], list
);
183 spin_unlock_irqrestore(&rl
->lock
, flags
);
187 * zfcp_reqlist_apply_for_all() - apply a function to every request.
188 * @rl: the requestlist that contains the target requests.
189 * @f: the function to apply to each request; the first parameter of the
190 * function will be the target-request; the second parameter is the same
191 * pointer as given with the argument @data.
192 * @data: freely chosen argument; passed through to @f as second parameter.
194 * Uses :c:macro:`list_for_each_entry` to iterate over the lists in the hash-
195 * table (not a 'safe' variant, so don't modify the list).
197 * Holds @rl->lock over the entire request-iteration.
200 zfcp_reqlist_apply_for_all(struct zfcp_reqlist
*rl
,
201 void (*f
)(struct zfcp_fsf_req
*, void *), void *data
)
203 struct zfcp_fsf_req
*req
;
207 spin_lock_irqsave(&rl
->lock
, flags
);
208 for (i
= 0; i
< ZFCP_REQ_LIST_BUCKETS
; i
++)
209 list_for_each_entry(req
, &rl
->buckets
[i
], list
)
211 spin_unlock_irqrestore(&rl
->lock
, flags
);
214 #endif /* ZFCP_REQLIST_H */