|  | @@ -0,0 +1,77 @@
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * Functions related to io context handling
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +#include <linux/kernel.h>
 | 
	
		
			
				|  |  | +#include <linux/module.h>
 | 
	
		
			
				|  |  | +#include <linux/init.h>
 | 
	
		
			
				|  |  | +#include <linux/bio.h>
 | 
	
		
			
				|  |  | +#include <linux/blkdev.h>
 | 
	
		
			
				|  |  | +#include <linux/bootmem.h>	/* for max_pfn/max_low_pfn */
 | 
	
		
			
				|  |  | +#include <linux/slab.h>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#include "blk.h"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * For io context allocations
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +static struct kmem_cache *iocontext_cachep;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * get_io_context - increment reference count to io_context
 | 
	
		
			
				|  |  | + * @ioc: io_context to get
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Increment reference count to @ioc.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +void get_io_context(struct io_context *ioc)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	BUG_ON(atomic_long_read(&ioc->refcount) <= 0);
 | 
	
		
			
				|  |  | +	atomic_long_inc(&ioc->refcount);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +EXPORT_SYMBOL(get_io_context);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void icq_free_icq_rcu(struct rcu_head *head)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	struct io_cq *icq = container_of(head, struct io_cq, __rcu_head);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	kmem_cache_free(icq->__rcu_icq_cache, icq);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* Exit an icq. Called with both ioc and q locked. */
 | 
	
		
			
				|  |  | +static void ioc_exit_icq(struct io_cq *icq)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	struct elevator_type *et = icq->q->elevator->type;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (icq->flags & ICQ_EXITED)
 | 
	
		
			
				|  |  | +		return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (et->ops.elevator_exit_icq_fn)
 | 
	
		
			
				|  |  | +		et->ops.elevator_exit_icq_fn(icq);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	icq->flags |= ICQ_EXITED;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* Release an icq.  Called with both ioc and q locked. */
 | 
	
		
			
				|  |  | +static void ioc_destroy_icq(struct io_cq *icq)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	struct io_context *ioc = icq->ioc;
 | 
	
		
			
				|  |  | +	struct request_queue *q = icq->q;
 | 
	
		
			
				|  |  | +	struct elevator_type *et = q->elevator->type;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	lockdep_assert_held(&ioc->lock);
 | 
	
		
			
				|  |  | +	lockdep_assert_held(q->queue_lock);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	radix_tree_delete(&ioc->icq_tree, icq->q->id);
 | 
	
		
			
				|  |  | +	hlist_del_init(&icq->ioc_node);
 | 
	
		
			
				|  |  | +	list_del_init(&icq->q_node);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * Both setting lookup hint to and clearing it from @icq are done
 | 
	
		
			
				|  |  | +	 * under queue_lock.  If it's not pointing to @icq now, it never
 | 
	
		
			
				|  |  | +	 * will.  Hint assignment itself can race safely.
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	if (rcu_dereference_raw(ioc->icq_hint) == icq)
 | 
	
		
			
				|  |  | +		rcu_assign_pointer(ioc->icq_hint, NULL);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	ioc_exit_icq(icq);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 |