/* SPDX-License-Identifier: GPL-2.0 */
/*
* zfcp device driver
*
* Data structure and helper functions for tracking pending FSF
* requests .
*
* Copyright IBM Corp . 2009 , 2023
*/
#ifndef ZFCP_REQLIST_H
#define ZFCP_REQLIST_H
#include <linux/types.h>
/* number of hash buckets */
#define ZFCP_REQ_LIST_BUCKETS 128 u
/**
* struct zfcp_reqlist - Container for request list ( reqlist )
* @ lock : Spinlock for protecting the hash list
* @ buckets : Array of hashbuckets , each is a list of requests in this bucket
*/
struct zfcp_reqlist {
spinlock_t lock;
struct list_head buckets[ZFCP_REQ_LIST_BUCKETS];
};
static inline size_t zfcp_reqlist_hash(u64 req_id)
{
return req_id % ZFCP_REQ_LIST_BUCKETS;
}
/**
* zfcp_reqlist_alloc - Allocate and initialize reqlist
*
* Returns pointer to allocated reqlist on success , or NULL on
* allocation failure .
*/
static inline struct zfcp_reqlist *zfcp_reqlist_alloc(void )
{
size_t i;
struct zfcp_reqlist *rl;
rl = kzalloc(sizeof (struct zfcp_reqlist), GFP_KERNEL);
if (!rl)
return NULL;
spin_lock_init(&rl->lock);
for (i = 0 ; i < ZFCP_REQ_LIST_BUCKETS; i++)
INIT_LIST_HEAD(&rl->buckets[i]);
return rl;
}
/**
* zfcp_reqlist_isempty - Check whether the request list empty
* @ rl : pointer to reqlist
*
* Returns : 1 if list is empty , 0 if not
*/
static inline int zfcp_reqlist_isempty(struct zfcp_reqlist *rl)
{
size_t i;
for (i = 0 ; i < ZFCP_REQ_LIST_BUCKETS; i++)
if (!list_empty(&rl->buckets[i]))
return 0 ;
return 1 ;
}
/**
* zfcp_reqlist_free - Free allocated memory for reqlist
* @ rl : The reqlist where to free memory
*/
static inline void zfcp_reqlist_free(struct zfcp_reqlist *rl)
{
/* sanity check */
BUG_ON(!zfcp_reqlist_isempty(rl));
kfree(rl);
}
static inline struct zfcp_fsf_req *
_zfcp_reqlist_find(struct zfcp_reqlist *rl, u64 req_id)
{
struct zfcp_fsf_req *req;
size_t i;
i = zfcp_reqlist_hash(req_id);
list_for_each_entry(req, &rl->buckets[i], list)
if (req->req_id == req_id)
return req;
return NULL;
}
/**
* zfcp_reqlist_find - Lookup FSF request by its request id
* @ rl : The reqlist where to lookup the FSF request
* @ req_id : The request id to look for
*
* Returns a pointer to the FSF request with the specified request id
* or NULL if there is no known FSF request with this id .
*/
static inline struct zfcp_fsf_req *
zfcp_reqlist_find(struct zfcp_reqlist *rl, u64 req_id)
{
unsigned long flags;
struct zfcp_fsf_req *req;
spin_lock_irqsave(&rl->lock, flags);
req = _zfcp_reqlist_find(rl, req_id);
spin_unlock_irqrestore(&rl->lock, flags);
return req;
}
/**
* zfcp_reqlist_find_rm - Lookup request by id and remove it from reqlist
* @ rl : reqlist where to search and remove entry
* @ req_id : The request id of the request to look for
*
* This functions tries to find the FSF request with the specified
* id and then removes it from the reqlist . The reqlist lock is held
* during both steps of the operation .
*
* Returns : Pointer to the FSF request if the request has been found ,
* NULL if it has not been found .
*/
static inline struct zfcp_fsf_req *
zfcp_reqlist_find_rm(struct zfcp_reqlist *rl, u64 req_id)
{
unsigned long flags;
struct zfcp_fsf_req *req;
spin_lock_irqsave(&rl->lock, flags);
req = _zfcp_reqlist_find(rl, req_id);
if (req)
list_del(&req->list);
spin_unlock_irqrestore(&rl->lock, flags);
return req;
}
/**
* zfcp_reqlist_add - Add entry to reqlist
* @ rl : reqlist where to add the entry
* @ req : The entry to add
*
* The request id always increases . As an optimization new requests
* are added here with list_add_tail at the end of the bucket lists
* while old requests are looked up starting at the beginning of the
* lists .
*/
static inline void zfcp_reqlist_add(struct zfcp_reqlist *rl,
struct zfcp_fsf_req *req)
{
size_t i;
unsigned long flags;
i = zfcp_reqlist_hash(req->req_id);
spin_lock_irqsave(&rl->lock, flags);
list_add_tail(&req->list, &rl->buckets[i]);
spin_unlock_irqrestore(&rl->lock, flags);
}
/**
* zfcp_reqlist_move - Move all entries from reqlist to simple list
* @ rl : The zfcp_reqlist where to remove all entries
* @ list : The list where to move all entries
*/
static inline void zfcp_reqlist_move(struct zfcp_reqlist *rl,
struct list_head *list)
{
size_t i;
unsigned long flags;
spin_lock_irqsave(&rl->lock, flags);
for (i = 0 ; i < ZFCP_REQ_LIST_BUCKETS; i++)
list_splice_init(&rl->buckets[i], list);
spin_unlock_irqrestore(&rl->lock, flags);
}
/**
* zfcp_reqlist_apply_for_all ( ) - apply a function to every request .
* @ rl : the requestlist that contains the target requests .
* @ f : the function to apply to each request ; the first parameter of the
* function will be the target - request ; the second parameter is the same
* pointer as given with the argument @ data .
* @ data : freely chosen argument ; passed through to @ f as second parameter .
*
* Uses : c : macro : ` list_for_each_entry ` to iterate over the lists in the hash -
* table ( not a ' safe ' variant , so don ' t modify the list ) .
*
* Holds @ rl - > lock over the entire request - iteration .
*/
static inline void
zfcp_reqlist_apply_for_all(struct zfcp_reqlist *rl,
void (*f)(struct zfcp_fsf_req *, void *), void *data)
{
struct zfcp_fsf_req *req;
unsigned long flags;
size_t i;
spin_lock_irqsave(&rl->lock, flags);
for (i = 0 ; i < ZFCP_REQ_LIST_BUCKETS; i++)
list_for_each_entry(req, &rl->buckets[i], list)
f(req, data);
spin_unlock_irqrestore(&rl->lock, flags);
}
#endif /* ZFCP_REQLIST_H */
Messung V0.5 in Prozent C=94 H=98 G=95
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-09-27)
¤
*© Formatika GbR, Deutschland