ia64/linux-2.6.18-xen.hg

changeset 6:4763065c587c

Imported patch blktap-aio-16_03_06.patch from xen-unstable.hg 15200:bd3d6b4c52ec
author Ian Campbell <ian.campbell@xensource.com>
date Mon Jun 04 10:05:23 2007 +0100 (2007-06-04)
parents 405dae994591
children 18d84fce4960
files fs/aio.c fs/eventpoll.c include/linux/aio.h include/linux/eventpoll.h
line diff
     1.1 --- a/fs/aio.c	Mon Jun 04 10:05:23 2007 +0100
     1.2 +++ b/fs/aio.c	Mon Jun 04 10:05:23 2007 +0100
     1.3 @@ -34,6 +34,11 @@
     1.4  #include <asm/uaccess.h>
     1.5  #include <asm/mmu_context.h>
     1.6  
     1.7 +#ifdef CONFIG_EPOLL
     1.8 +#include <linux/poll.h>
     1.9 +#include <linux/eventpoll.h>
    1.10 +#endif
    1.11 +
    1.12  #if DEBUG > 1
    1.13  #define dprintk		printk
    1.14  #else
    1.15 @@ -1015,6 +1020,10 @@ put_rq:
    1.16  	if (waitqueue_active(&ctx->wait))
    1.17  		wake_up(&ctx->wait);
    1.18  
    1.19 +#ifdef CONFIG_EPOLL
    1.20 +	if (ctx->file && waitqueue_active(&ctx->poll_wait))
    1.21 +		wake_up(&ctx->poll_wait);
    1.22 +#endif
    1.23  	if (ret)
    1.24  		put_ioctx(ctx);
    1.25  
    1.26 @@ -1024,6 +1033,8 @@ put_rq:
    1.27  /* aio_read_evt
    1.28   *	Pull an event off of the ioctx's event ring.  Returns the number of 
    1.29   *	events fetched (0 or 1 ;-)
    1.30 + *	If ent parameter is 0, just returns the number of events that would
    1.31 + *	be fetched.
    1.32   *	FIXME: make this use cmpxchg.
    1.33   *	TODO: make the ringbuffer user mmap()able (requires FIXME).
    1.34   */
    1.35 @@ -1046,13 +1057,18 @@ static int aio_read_evt(struct kioctx *i
    1.36  
    1.37  	head = ring->head % info->nr;
    1.38  	if (head != ring->tail) {
    1.39 -		struct io_event *evp = aio_ring_event(info, head, KM_USER1);
    1.40 -		*ent = *evp;
    1.41 -		head = (head + 1) % info->nr;
    1.42 -		smp_mb(); /* finish reading the event before updatng the head */
    1.43 -		ring->head = head;
    1.44 -		ret = 1;
    1.45 -		put_aio_ring_event(evp, KM_USER1);
    1.46 +		if (ent) { /* event requested */
    1.47 +			struct io_event *evp =
    1.48 +				aio_ring_event(info, head, KM_USER1);
    1.49 +			*ent = *evp;
    1.50 +			head = (head + 1) % info->nr;
    1.51 +			/* finish reading the event before updatng the head */
    1.52 +			smp_mb();
    1.53 +			ring->head = head;
    1.54 +			ret = 1;
    1.55 +			put_aio_ring_event(evp, KM_USER1);
    1.56 +		} else /* only need to know availability */
    1.57 +			ret = 1;
    1.58  	}
    1.59  	spin_unlock(&info->ring_lock);
    1.60  
    1.61 @@ -1235,9 +1251,78 @@ static void io_destroy(struct kioctx *io
    1.62  
    1.63  	aio_cancel_all(ioctx);
    1.64  	wait_for_all_aios(ioctx);
    1.65 +#ifdef CONFIG_EPOLL
    1.66 +	/* forget the poll file, but it's up to the user to close it */
    1.67 +	if (ioctx->file) {
    1.68 +		ioctx->file->private_data = 0;
    1.69 +		ioctx->file = 0;
    1.70 +	}
    1.71 +#endif
    1.72  	put_ioctx(ioctx);	/* once for the lookup */
    1.73  }
    1.74  
    1.75 +#ifdef CONFIG_EPOLL
    1.76 +
    1.77 +static int aio_queue_fd_close(struct inode *inode, struct file *file)
    1.78 +{
    1.79 +	struct kioctx *ioctx = file->private_data;
    1.80 +	if (ioctx) {
    1.81 +		file->private_data = 0;
    1.82 +		spin_lock_irq(&ioctx->ctx_lock);
    1.83 +		ioctx->file = 0;
    1.84 +		spin_unlock_irq(&ioctx->ctx_lock);
    1.85 +	}
    1.86 +	return 0;
    1.87 +}
    1.88 +
    1.89 +static unsigned int aio_queue_fd_poll(struct file *file, poll_table *wait)
    1.90 +{	unsigned int pollflags = 0;
    1.91 +	struct kioctx *ioctx = file->private_data;
    1.92 +
    1.93 +	if (ioctx) {
    1.94 +
    1.95 +		spin_lock_irq(&ioctx->ctx_lock);
    1.96 +		/* Insert inside our poll wait queue */
    1.97 +		poll_wait(file, &ioctx->poll_wait, wait);
    1.98 +
    1.99 +		/* Check our condition */
   1.100 +		if (aio_read_evt(ioctx, 0))
   1.101 +			pollflags = POLLIN | POLLRDNORM;
   1.102 +		spin_unlock_irq(&ioctx->ctx_lock);
   1.103 +	}
   1.104 +
   1.105 +	return pollflags;
   1.106 +}
   1.107 +
   1.108 +static const struct file_operations aioq_fops = {
   1.109 +	.release	= aio_queue_fd_close,
   1.110 +	.poll		= aio_queue_fd_poll
   1.111 +};
   1.112 +
   1.113 +/* make_aio_fd:
   1.114 + *  Create a file descriptor that can be used to poll the event queue.
   1.115 + *  Based and piggybacked on the excellent epoll code.
   1.116 + */
   1.117 +
   1.118 +static int make_aio_fd(struct kioctx *ioctx)
   1.119 +{
   1.120 +	int error, fd;
   1.121 +	struct inode *inode;
   1.122 +	struct file *file;
   1.123 +
   1.124 +	error = ep_getfd(&fd, &inode, &file, NULL, &aioq_fops);
   1.125 +	if (error)
   1.126 +		return error;
   1.127 +
   1.128 +	/* associate the file with the IO context */
   1.129 +	file->private_data = ioctx;
   1.130 +	ioctx->file = file;
   1.131 +	init_waitqueue_head(&ioctx->poll_wait);
   1.132 +	return fd;
   1.133 +}
   1.134 +#endif
   1.135 +
   1.136 +
   1.137  /* sys_io_setup:
   1.138   *	Create an aio_context capable of receiving at least nr_events.
   1.139   *	ctxp must not point to an aio_context that already exists, and
   1.140 @@ -1250,18 +1335,30 @@ static void io_destroy(struct kioctx *io
   1.141   *	resources are available.  May fail with -EFAULT if an invalid
   1.142   *	pointer is passed for ctxp.  Will fail with -ENOSYS if not
   1.143   *	implemented.
   1.144 + *
   1.145 + *	To request a selectable fd, the user context has to be initialized
   1.146 + *	to 1, instead of 0, and the return value is the fd.
   1.147 + *	This keeps the system call compatible, since a non-zero value
   1.148 + *	was not allowed so far.
   1.149   */
   1.150  asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t __user *ctxp)
   1.151  {
   1.152  	struct kioctx *ioctx = NULL;
   1.153  	unsigned long ctx;
   1.154  	long ret;
   1.155 +	int make_fd = 0;
   1.156  
   1.157  	ret = get_user(ctx, ctxp);
   1.158  	if (unlikely(ret))
   1.159  		goto out;
   1.160  
   1.161  	ret = -EINVAL;
   1.162 +#ifdef CONFIG_EPOLL
   1.163 +	if (ctx == 1) {
   1.164 +		make_fd = 1;
   1.165 +		ctx = 0;
   1.166 +	}
   1.167 +#endif
   1.168  	if (unlikely(ctx || nr_events == 0)) {
   1.169  		pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n",
   1.170  		         ctx, nr_events);
   1.171 @@ -1272,8 +1369,12 @@ asmlinkage long sys_io_setup(unsigned nr
   1.172  	ret = PTR_ERR(ioctx);
   1.173  	if (!IS_ERR(ioctx)) {
   1.174  		ret = put_user(ioctx->user_id, ctxp);
   1.175 -		if (!ret)
   1.176 -			return 0;
   1.177 +#ifdef CONFIG_EPOLL
   1.178 +		if (make_fd && ret >= 0)
   1.179 +			ret = make_aio_fd(ioctx);
   1.180 +#endif
   1.181 +		if (ret >= 0)
   1.182 +			return ret;
   1.183  
   1.184  		get_ioctx(ioctx); /* io_destroy() expects us to hold a ref */
   1.185  		io_destroy(ioctx);
     2.1 --- a/fs/eventpoll.c	Mon Jun 04 10:05:23 2007 +0100
     2.2 +++ b/fs/eventpoll.c	Mon Jun 04 10:05:23 2007 +0100
     2.3 @@ -236,8 +236,6 @@ struct ep_pqueue {
     2.4  
     2.5  static void ep_poll_safewake_init(struct poll_safewake *psw);
     2.6  static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq);
     2.7 -static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
     2.8 -		    struct eventpoll *ep);
     2.9  static int ep_alloc(struct eventpoll **pep);
    2.10  static void ep_free(struct eventpoll *ep);
    2.11  static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd);
    2.12 @@ -267,7 +265,7 @@ static int ep_events_transfer(struct eve
    2.13  static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
    2.14  		   int maxevents, long timeout);
    2.15  static int eventpollfs_delete_dentry(struct dentry *dentry);
    2.16 -static struct inode *ep_eventpoll_inode(void);
    2.17 +static struct inode *ep_eventpoll_inode(const struct file_operations *fops);
    2.18  static int eventpollfs_get_sb(struct file_system_type *fs_type,
    2.19  			      int flags, const char *dev_name,
    2.20  			      void *data, struct vfsmount *mnt);
    2.21 @@ -517,7 +515,7 @@ asmlinkage long sys_epoll_create(int siz
    2.22  	 * Creates all the items needed to setup an eventpoll file. That is,
    2.23  	 * a file structure, and inode and a free file descriptor.
    2.24  	 */
    2.25 -	error = ep_getfd(&fd, &inode, &file, ep);
    2.26 +	error = ep_getfd(&fd, &inode, &file, ep, &eventpoll_fops);
    2.27  	if (error)
    2.28  		goto eexit_2;
    2.29  
    2.30 @@ -702,8 +700,8 @@ eexit_1:
    2.31  /*
    2.32   * Creates the file descriptor to be used by the epoll interface.
    2.33   */
    2.34 -static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
    2.35 -		    struct eventpoll *ep)
    2.36 +int ep_getfd(int *efd, struct inode **einode, struct file **efile,
    2.37 +		    struct eventpoll *ep, const struct file_operations *fops)
    2.38  {
    2.39  	struct qstr this;
    2.40  	char name[32];
    2.41 @@ -719,7 +717,7 @@ static int ep_getfd(int *efd, struct ino
    2.42  		goto eexit_1;
    2.43  
    2.44  	/* Allocates an inode from the eventpoll file system */
    2.45 -	inode = ep_eventpoll_inode();
    2.46 +	inode = ep_eventpoll_inode(fops);
    2.47  	error = PTR_ERR(inode);
    2.48  	if (IS_ERR(inode))
    2.49  		goto eexit_2;
    2.50 @@ -750,7 +748,7 @@ static int ep_getfd(int *efd, struct ino
    2.51  
    2.52  	file->f_pos = 0;
    2.53  	file->f_flags = O_RDONLY;
    2.54 -	file->f_op = &eventpoll_fops;
    2.55 +	file->f_op = fops;
    2.56  	file->f_mode = FMODE_READ;
    2.57  	file->f_version = 0;
    2.58  	file->private_data = ep;
    2.59 @@ -1569,7 +1567,7 @@ static int eventpollfs_delete_dentry(str
    2.60  }
    2.61  
    2.62  
    2.63 -static struct inode *ep_eventpoll_inode(void)
    2.64 +static struct inode *ep_eventpoll_inode(const struct file_operations *fops)
    2.65  {
    2.66  	int error = -ENOMEM;
    2.67  	struct inode *inode = new_inode(eventpoll_mnt->mnt_sb);
    2.68 @@ -1577,7 +1575,7 @@ static struct inode *ep_eventpoll_inode(
    2.69  	if (!inode)
    2.70  		goto eexit_1;
    2.71  
    2.72 -	inode->i_fop = &eventpoll_fops;
    2.73 +	inode->i_fop = fops;
    2.74  
    2.75  	/*
    2.76  	 * Mark the inode dirty from the very beginning,
     3.1 --- a/include/linux/aio.h	Mon Jun 04 10:05:23 2007 +0100
     3.2 +++ b/include/linux/aio.h	Mon Jun 04 10:05:23 2007 +0100
     3.3 @@ -191,6 +191,11 @@ struct kioctx {
     3.4  	struct aio_ring_info	ring_info;
     3.5  
     3.6  	struct work_struct	wq;
     3.7 +#ifdef CONFIG_EPOLL
     3.8 +	// poll integration
     3.9 +	wait_queue_head_t       poll_wait;
    3.10 +	struct file		*file;
    3.11 +#endif
    3.12  };
    3.13  
    3.14  /* prototypes */
     4.1 --- a/include/linux/eventpoll.h	Mon Jun 04 10:05:23 2007 +0100
     4.2 +++ b/include/linux/eventpoll.h	Mon Jun 04 10:05:23 2007 +0100
     4.3 @@ -90,6 +90,12 @@ static inline void eventpoll_release(str
     4.4  	eventpoll_release_file(file);
     4.5  }
     4.6  
     4.7 +/*
     4.8 + * called by aio code to create fd that can poll the  aio event queueQ
     4.9 + */
    4.10 +struct eventpoll;
    4.11 +int ep_getfd(int *efd, struct inode **einode, struct file **efile,
    4.12 +             struct eventpoll *ep, const struct file_operations *fops);
    4.13  #else
    4.14  
    4.15  static inline void eventpoll_init_file(struct file *file) {}