123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- /*
- * zfcp device driver
- *
- * Data structure and helper functions for tracking pending FSF
- * requests.
- *
- * Copyright IBM Corp. 2009, 2016
- */
- #ifndef ZFCP_REQLIST_H
- #define ZFCP_REQLIST_H
- /* number of hash buckets */
- #define ZFCP_REQ_LIST_BUCKETS 128
- /**
- * struct zfcp_reqlist - Container for request list (reqlist)
- * @lock: Spinlock for protecting the hash list
- * @list: 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 int zfcp_reqlist_hash(unsigned long 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)
- {
- unsigned int 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)
- {
- unsigned int 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, unsigned long req_id)
- {
- struct zfcp_fsf_req *req;
- unsigned int 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, unsigned long 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, unsigned long 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)
- {
- unsigned int 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)
- {
- unsigned int 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;
- unsigned int 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 */
|