mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 5/5] Add support for AIO cancelation against a file descriptor
@ 2005-07-28 15:46 Sébastien Dugué
  0 siblings, 0 replies; only message in thread
From: Sébastien Dugué @ 2005-07-28 15:46 UTC (permalink / raw)
  To: linux-aio kvack.org, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1 bytes --]



[-- Attachment #2: cancelfd --]
[-- Type: application/octet-stream, Size: 5919 bytes --]

cancelfd:

This patch adds support for POSIX AIO cancelation against a file descriptor.


 Makefile                |    2
 fs/aio.c                |  141 +++++++++++++++++++++++++++++++++++++-----------
 include/linux/aio_abi.h |    6 ++
 3 files changed, 118 insertions(+), 31 deletions(-)

Signed-off-by: Sébastien Dugué <sebastien.dugue@bull.net>

Index: linux-2.6.12/fs/aio.c
===================================================================
--- linux-2.6.12.orig/fs/aio.c	2005-07-21 11:43:26.000000000 +0200
+++ linux-2.6.12/fs/aio.c	2005-07-21 11:43:27.000000000 +0200
@@ -263,6 +263,28 @@
 	return ctx;
 }
 
+static int __aio_cancel(struct kiocb *kiocb, struct io_event *result)
+{
+	int (*cancel)(struct kiocb *iocb, struct io_event *res);
+
+	if (kiocb == NULL)
+		return -EFAULT;
+
+	cancel = kiocb->ki_cancel;
+	if (NULL == cancel) {
+		printk(KERN_DEBUG "iocb has no cancel operation\n");
+		return -EFAULT;
+	}
+
+	kiocb->ki_users ++;
+
+	memset(result, 0, sizeof(*result));
+	result->obj = (u64)(unsigned long)kiocb->ki_obj.user;
+	result->data = kiocb->ki_user_data;
+
+	return cancel(kiocb, result);
+}
+
 /* aio_cancel_all
  *	Cancels all outstanding aio requests on an aio context.  Used 
  *	when the processes owning a context have all exited to encourage 
@@ -270,7 +292,6 @@
  */
 static void aio_cancel_all(struct kioctx *ctx)
 {
-	int (*cancel)(struct kiocb *, struct io_event *);
 	struct io_event res;
 	spin_lock_irq(&ctx->ctx_lock);
 	ctx->dead = 1;
@@ -278,14 +299,10 @@
 		struct list_head *pos = ctx->active_reqs.next;
 		struct kiocb *iocb = list_kiocb(pos);
 		list_del_init(&iocb->ki_list);
-		cancel = iocb->ki_cancel;
 		kiocbSetCancelled(iocb);
-		if (cancel) {
-			iocb->ki_users++;
-			spin_unlock_irq(&ctx->ctx_lock);
-			cancel(iocb, &res);
-			spin_lock_irq(&ctx->ctx_lock);
-		}
+		spin_unlock_irq(&ctx->ctx_lock);
+		__aio_cancel(iocb, &res);
+		spin_lock_irq(&ctx->ctx_lock);
 	}
 	spin_unlock_irq(&ctx->ctx_lock);
 }
@@ -2028,6 +2045,67 @@
 	return NULL;
 }
 
+static int aio_cancel_fd(aio_context_t ctx_id, int fildes)
+{
+	struct kioctx *ctx;
+	struct kiocb *kiocb;
+	int ret;
+	struct file *file;
+	struct list_head *pos;
+	int all_done;
+	int not_canceled;
+	struct io_event result_event;
+
+	/* cancel all I/O belonging to filedes */
+
+	file = fget(fildes);
+	if (unlikely(!file))
+		return -EBADF;
+
+	/* we must exit on EBADF before EINVAL */
+
+	ctx = lookup_ioctx(ctx_id);
+	if (unlikely(!ctx)) {
+		return -EINVAL;
+	}
+
+	/* get all operation for this file descriptor */
+
+	all_done = 1;
+	not_canceled = 0;
+	spin_lock_irq(&ctx->ctx_lock);
+
+	list_for_each(pos, &ctx->active_reqs) {
+
+		kiocb = list_kiocb(pos);
+
+		if (kiocb->ki_filp == file) {
+
+			all_done = 0;
+
+			spin_unlock_irq(&ctx->ctx_lock);
+			ret = __aio_cancel(kiocb, &result_event);
+			spin_lock_irq(&ctx->ctx_lock);
+			if (ret)
+				not_canceled++;
+			else
+				__aio_write_evt(kiocb->ki_ctx, &result_event);
+		}
+	}
+
+	spin_unlock_irq(&ctx->ctx_lock);
+
+	put_ioctx(ctx);
+
+	if (all_done)
+		return AIO_ALLDONE;
+
+	if (not_canceled)
+		return AIO_NOTCANCELED;
+
+	return AIO_CANCELED;
+}
+
 /* sys_io_cancel:
  *	Attempts to cancel an iocb previously passed to io_submit.  If
  *	the operation is successfully cancelled, the resulting event is
@@ -2041,9 +2119,9 @@
 asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb,
 			      struct io_event __user *result)
 {
-	int (*cancel)(struct kiocb *iocb, struct io_event *res);
 	struct kioctx *ctx;
 	struct kiocb *kiocb;
+	struct io_event tmp;
 	u32 key;
 	int ret;
 
@@ -2051,37 +2129,40 @@
 	if (unlikely(ret))
 		return -EFAULT;
 
+	if ( (key == 0) &&  (result == NULL) ) {
+		/* cancel all IOCBs belonging to iocb->aio_fildes */
+
+		ret = aio_cancel_fd(ctx_id, iocb->aio_fildes);
+
+		return ret;
+	}
+
 	ctx = lookup_ioctx(ctx_id);
 	if (unlikely(!ctx))
 		return -EINVAL;
 
 	spin_lock_irq(&ctx->ctx_lock);
-	ret = -EAGAIN;
 	kiocb = lookup_kiocb(ctx, iocb, key);
-	if (kiocb && kiocb->ki_cancel) {
-		cancel = kiocb->ki_cancel;
-		kiocb->ki_users ++;
-		kiocbSetCancelled(kiocb);
-	} else
-		cancel = NULL;
 	spin_unlock_irq(&ctx->ctx_lock);
 
-	if (NULL != cancel) {
-		struct io_event tmp;
-		pr_debug("calling cancel\n");
-		memset(&tmp, 0, sizeof(tmp));
-		tmp.obj = (u64)(unsigned long)kiocb->ki_obj.user;
-		tmp.data = kiocb->ki_user_data;
-		ret = cancel(kiocb, &tmp);
-		if (!ret) {
-			/* Cancellation succeeded -- copy the result
-			 * into the user's buffer.
-			 */
+	if (kiocb == NULL) {
+		put_ioctx(ctx);
+		return -EINVAL;
+	}
+ 
+	ret = __aio_cancel(kiocb, &tmp);
+	if (!ret) {
+		/* Cancellation succeeded -- copy the result
+		 * into the user's buffer.
+		 */
+		if (result == NULL) {
+			spin_lock_irq(&ctx->ctx_lock);
+			__aio_write_evt(kiocb->ki_ctx, &tmp);
+			spin_unlock_irq(&ctx->ctx_lock);
+		} else
 			if (copy_to_user(result, &tmp, sizeof(tmp)))
 				ret = -EFAULT;
-		}
-	} else
-		printk(KERN_DEBUG "iocb has no cancel operation\n");
+	}
 
 	put_ioctx(ctx);
 
Index: linux-2.6.12/include/linux/aio_abi.h
===================================================================
--- linux-2.6.12.orig/include/linux/aio_abi.h	2005-07-21 11:43:26.000000000 +0200
+++ linux-2.6.12/include/linux/aio_abi.h	2005-07-21 11:43:27.000000000 +0200
@@ -45,6 +45,12 @@
 	IOCB_CMD_CHECKPOINT = 8,
 };
 
+enum {
+	AIO_CANCELED = 0,
+	AIO_NOTCANCELED = 1,
+	AIO_ALLDONE = 2,
+};
+
 /* read() from /dev/aio returns these structures. */
 struct io_event {
 	__u64		data;		/* the data field from the iocb */
Index: linux-2.6.12/Makefile
===================================================================
--- linux-2.6.12.orig/Makefile	2005-07-21 11:43:26.000000000 +0200
+++ linux-2.6.12/Makefile	2005-07-21 11:43:27.000000000 +0200
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 12
-EXTRAVERSION = .PAIO-liowait
+EXTRAVERSION = .PAIO
 NAME=Woozy Numbat
 
 # *DOCUMENTATION*

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-07-28 15:48 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-07-28 15:46 [PATCH 5/5] Add support for AIO cancelation against a file descriptor Sébastien Dugué

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®