mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 3/5] Add support for LIO completion notification
@ 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: lioevent --]
[-- Type: application/octet-stream, Size: 8157 bytes --]

lioevent:

 This patch adds POSIX listio completion notification event. This works by
adding an IOCB_CMD_EVENT command.

 As part of listio submission, the user may choose to create an empty aiocb
with an aio_lio_opcode of IOCB_CMD_EVENT and filling only the aio_sigevent fields.

 Upon list completion, the kernel notifies the application using those sigevent
parameters.


 Makefile                |    2
 fs/aio.c                |  155 ++++++++++++++++++++++++++++++++++++++++++++++--
 include/linux/aio.h     |   14 +++-
 include/linux/aio_abi.h |    1
 4 files changed, 164 insertions(+), 8 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-08 14:38:39.000000000 +0200
+++ linux-2.6.12/fs/aio.c	2005-07-21 11:43:17.000000000 +0200
@@ -410,6 +410,7 @@
 	req->ki_signo = 0;
 	req->ki_notify = 0;
 	req->ki_value = 0;
+	req->ki_lio_event = NULL;
 	req->private = NULL;
 	INIT_LIST_HEAD(&req->ki_run_list);
 
@@ -953,6 +954,101 @@
 	read_unlock(&tasklist_lock);
 }
 
+static inline void check_lio(struct kioctx *ctx, 
+			     struct lio_event *lio)
+{
+	int ret;
+
+	if (lio == NULL)
+		return;
+
+	ret = atomic_dec_and_test(&(lio->lio_users));
+
+	if (lio->lio_signo) {
+
+		if (likely(ret)) {
+
+			/* last one -> notify process */
+			__aio_send_signal(lio->lio_pid, 
+					  lio->lio_signo, 
+				  	  lio->lio_notify,
+					  (void*)(unsigned long)lio->lio_value);
+
+			/* free memory */
+
+			kfree(lio);
+		}
+
+	}
+}
+
+static int create_lio_event(struct kioctx *ctx,struct lio_event **lio,
+			    pid_t pid, int signo, void *value)
+{
+	int notify;
+
+	if (pid == 0) {
+		/* notify itself */
+
+		pid = current->pid;
+		notify = IO_NOTIFY_SIGNAL;
+	} else {
+		pid_t group_id;
+		task_t *ptask;
+
+		/* notify given thread */
+
+		/* caller thread and target thread must be in same
+		 * thread group
+		 */
+
+		read_lock(&tasklist_lock);
+		ptask = find_task_by_pid(pid);
+
+		if (unlikely (ptask == NULL)) {
+			read_unlock(&tasklist_lock);
+			return -EFAULT;
+		}
+
+		group_id = ptask->tgid;
+		read_unlock(&tasklist_lock);
+
+		if (group_id != current->tgid)
+			return -EINVAL;
+
+		notify = IO_NOTIFY_THREAD_ID;
+	}
+
+	/* we break an existing sequence (lio exists)
+	 * close the sequence
+	 */
+
+	check_lio(ctx, *lio);
+
+	if (signo == 0) {
+
+		/* it means we don't want to monitor following commands
+		 * usefull to break current sequence
+		 */
+		*lio = NULL;
+
+		return 0;
+	}
+
+
+	*lio = kmalloc(sizeof(*lio), GFP_KERNEL);
+	if (!*lio)
+		return -EAGAIN;
+
+	atomic_set(&((*lio)->lio_users), 1);
+	(*lio)->lio_pid = pid;
+	(*lio)->lio_signo = signo;
+	(*lio)->lio_notify = notify;
+	(*lio)->lio_value = (__u64)(unsigned long)value;
+
+	return 0;
+}
+
 static void __aio_write_evt(struct kioctx *ctx, struct io_event *event)
 {
 	struct aio_ring_info	*info;
@@ -1057,6 +1153,8 @@
 		__aio_send_signal(iocb->ki_pid, iocb->ki_signo, iocb->ki_notify,
 				  (void*)(unsigned long)iocb->ki_value);
 
+	check_lio(ctx, iocb->ki_lio_event);
+
 	pr_debug("%ld retries: %d of %d\n", iocb->ki_retried,
 		iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes);
 put_rq:
@@ -1440,6 +1538,7 @@
 
 	if (file->f_op->aio_fsync)
 		ret = file->f_op->aio_fsync(iocb, 0);
+
 	return ret;
 }
 
@@ -1528,7 +1627,7 @@
 }
 
 int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
-			 struct iocb *iocb)
+			 struct iocb *iocb, struct lio_event *lio)
 {
 	struct kiocb *req;
 	struct file *file;
@@ -1650,6 +1749,7 @@
 		req->ki_notify = notify;
 		req->ki_value = aio_value;
 	}
+	req->ki_lio_event = lio;
 
 	req->ki_buf = (char __user *)(unsigned long)iocb->aio_buf;
 	req->ki_left = req->ki_nbytes = iocb->aio_nbytes;
@@ -1697,6 +1797,7 @@
 asmlinkage long sys_io_submit(aio_context_t ctx_id, long nr,
 			      struct iocb __user * __user *iocbpp)
 {
+	struct lio_event *lio;
 	struct kioctx *ctx;
 	long ret = 0;
 	int i;
@@ -1717,13 +1818,15 @@
 	 * AKPM: should this return a partial result if some of the IOs were
 	 * successfully submitted?
 	 */
+
+	lio = NULL;
 	for (i=0; i<nr; i++) {
 		struct iocb __user *user_iocb;
 		struct iocb tmp;
 		struct sigevent __user *user_event = NULL;
 		int aio_pid = 0;
 		int aio_signo = 0;
-		
+		int aio_value = 0;
 
 		if (unlikely(__get_user(user_iocb, iocbpp + i))) {
 			ret = -EFAULT;
@@ -1771,12 +1874,54 @@
 				ret = -EFAULT;
 				break;
 			}
+
+			if (unlikely(__get_user(aio_value,
+						&user_event->sigev_value.sival_int))) {
+				ret = -EFAULT;
+				break;
+			}
 		}
 
-		ret = io_submit_one(ctx, user_iocb, &tmp);
-		if (ret)
-			break;
+		if (tmp.aio_lio_opcode == IOCB_CMD_EVENT) {
+
+			/* this command means that all following IO commands
+			 * are in the same group and when the group becomes
+			 * empty (all requests have been processed)
+			 * we must send a signal to a given process or thread
+			 */
+
+			ret = create_lio_event(ctx, &lio,
+					       aio_pid, aio_signo,
+					       (void *)aio_value);
+			if (ret)
+				break;
+
+			continue;
+		}
+
+		if (lio && ((tmp.aio_lio_opcode == IOCB_CMD_PREAD) ||
+			   (tmp.aio_lio_opcode == IOCB_CMD_PWRITE)) ) {
+
+			atomic_inc(&lio->lio_users);
+			ret = io_submit_one(ctx, user_iocb, &tmp, lio);
+
+			/*
+			 * If a request failed, just decrement the users count,
+			 * but go on submitting subsequent requests.
+			 *
+			 */
+			if (ret)
+				atomic_dec(&lio->lio_users);
+
+			continue;
+
+		} else {
+			ret = io_submit_one(ctx, user_iocb, &tmp, NULL);
+			if (ret)
+				break;
+		}
 	}
+	check_lio(ctx, lio);
 
 	put_ioctx(ctx);
 	return i ? i : ret;
Index: linux-2.6.12/include/linux/aio_abi.h
===================================================================
--- linux-2.6.12.orig/include/linux/aio_abi.h	2005-07-08 14:38:39.000000000 +0200
+++ linux-2.6.12/include/linux/aio_abi.h	2005-07-21 11:42:56.000000000 +0200
@@ -41,6 +41,7 @@
 	 * IOCB_CMD_POLL = 5,
 	 */
 	IOCB_CMD_NOOP = 6,
+	IOCB_CMD_EVENT = 7,
 };
 
 /* read() from /dev/aio returns these structures. */
Index: linux-2.6.12/include/linux/aio.h
===================================================================
--- linux-2.6.12.orig/include/linux/aio.h	2005-07-08 14:38:39.000000000 +0200
+++ linux-2.6.12/include/linux/aio.h	2005-07-21 11:30:02.000000000 +0200
@@ -48,6 +48,14 @@
 #define kiocbIsKicked(iocb)	test_bit(KIF_KICKED, &(iocb)->ki_flags)
 #define kiocbIsCancelled(iocb)	test_bit(KIF_CANCELLED, &(iocb)->ki_flags)
 
+struct lio_event {
+	atomic_t	lio_users;
+	__s32		lio_pid;
+	__u16		lio_signo;
+	__u16		lio_notify;
+	__u64		lio_value;
+};
+
 struct kiocb {
 	struct list_head	ki_run_list;
 	long			ki_flags;
@@ -83,6 +91,7 @@
 	__u16			ki_signo;
 	__u16			ki_notify;
 	__u64			ki_value;
+	struct lio_event	*ki_lio_event;
 
 	void			*private;
 };
@@ -176,12 +185,13 @@
 extern void FASTCALL(exit_aio(struct mm_struct *mm));
 extern struct kioctx *lookup_ioctx(unsigned long ctx_id);
 extern int FASTCALL(io_submit_one(struct kioctx *ctx,
-			struct iocb __user *user_iocb, struct iocb *iocb));
+			struct iocb __user *user_iocb, struct iocb *iocb,
+			struct lio_event *lio));
 
 /* semi private, but used by the 32bit emulations: */
 struct kioctx *lookup_ioctx(unsigned long ctx_id);
 int FASTCALL(io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
-				  struct iocb *iocb));
+				  struct iocb *iocb, struct lio_event *lio));
 
 #define get_ioctx(kioctx)	do { if (unlikely(atomic_read(&(kioctx)->users) <= 0)) BUG(); atomic_inc(&(kioctx)->users); } while (0)
 #define put_ioctx(kioctx)	do { if (unlikely(atomic_dec_and_test(&(kioctx)->users))) __put_ioctx(kioctx); else if (unlikely(atomic_read(&(kioctx)->users) < 0)) BUG(); } while (0)
Index: linux-2.6.12/Makefile
===================================================================
--- linux-2.6.12.orig/Makefile	2005-07-08 14:38:39.000000000 +0200
+++ linux-2.6.12/Makefile	2005-07-21 11:42:56.000000000 +0200
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 12
-EXTRAVERSION = .PAIO-aioevent
+EXTRAVERSION = .PAIO-lioevent
 NAME=Woozy Numbat
 
 # *DOCUMENTATION*

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

only message in thread, other threads:[~2005-07-28 16:03 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 3/5] Add support for LIO completion notification 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®