 b6bd2fb92a
			
		
	
	
	b6bd2fb92a
	
	
	
		
			
			Move the code for tracking FSF requests to new file to have this code in one place. The functions for adding and removing requests on the I/O path are already inline. The alloc and free functions are only called once, so it does not hurt to inline them and add them to the same file. Reviewed-by: Swen Schillig <swen@vnet.ibm.com> Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
		
			
				
	
	
		
			183 lines
		
	
	
	
		
			4.4 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			183 lines
		
	
	
	
		
			4.4 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * zfcp device driver
 | |
|  *
 | |
|  * Data structure and helper functions for tracking pending FSF
 | |
|  * requests.
 | |
|  *
 | |
|  * Copyright IBM Corporation 2009
 | |
|  */
 | |
| 
 | |
| #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);
 | |
| }
 | |
| 
 | |
| #endif /* ZFCP_REQLIST_H */
 |