diff -uprN -X dontdiff linux-2.6.8.1/fs/aio.c linux-2.6.8.1-aioevent/fs/aio.c
--- linux-2.6.8.1/fs/aio.c	2004-08-14 12:55:31.000000000 +0200
+++ linux-2.6.8.1-aioevent/fs/aio.c	2004-11-03 14:50:33.000000000 +0100
@@ -397,6 +397,10 @@ static struct kiocb fastcall *__aio_get_
 	req->ki_retry = NULL;
 	req->ki_obj.user = NULL;
 	req->ki_dtor = NULL;
+	req->ki_pid = 0;
+	req->ki_signo = 0;
+	req->ki_notify = 0;
+	req->ki_value = 0;
 	req->private = NULL;
 
 	/* Check if the completion queue has enough free space to
@@ -444,6 +448,9 @@ static inline void really_put_req(struct
 	req->ki_filp = NULL;
 	req->ki_obj.user = NULL;
 	req->ki_dtor = NULL;
+	req->ki_pid = 0;
+	req->ki_signo = 0;
+	req->ki_notify = 0;
 	req->private = NULL;
 	kmem_cache_free(kiocb_cachep, req);
 	ctx->reqs_active--;
@@ -626,6 +633,47 @@ void fastcall kick_iocb(struct kiocb *io
 }
 EXPORT_SYMBOL(kick_iocb);
 
+static void __aio_send_signal(pid_t pid, int signo, int notify, void *obj)
+{
+	struct siginfo info;
+	struct task_struct *p;
+
+	memset(&info, 0, sizeof(struct siginfo));
+
+	info.si_signo = signo;
+	info.si_errno = 0;
+	info.si_code = SI_ASYNCIO;
+	info.si_pid = 0;
+	info.si_uid = 0;
+	info.si_ptr = obj;
+
+	read_lock(&tasklist_lock);
+	p = find_task_by_pid(pid);
+
+	if (p->sighand) {
+		unsigned long flags;
+		int ret = -1;
+
+		spin_lock_irqsave(&p->sighand->siglock, flags);
+		switch(notify) {
+
+		case IO_NOTIFY_SIGNAL:
+			ret = __group_send_sig_info(signo, &info, p);
+			break;
+
+		case IO_NOTIFY_THREAD_ID:
+			ret = specific_send_sig_info(signo, &info, p);
+			break;
+		}
+		spin_unlock_irqrestore(&p->sighand->siglock, flags);
+		if (ret)
+			printk(KERN_DEBUG 
+			"__aio_send_signal: fail to send signal %d to %d\n",
+			signo, pid);
+	}
+	read_unlock(&tasklist_lock);
+}
+
 /* aio_complete
  *	Called when the io request on the given iocb is complete.
  *	Returns true if this is the last user of the request.  The 
@@ -703,6 +751,10 @@ int fastcall aio_complete(struct kiocb *
 
 	pr_debug("added to ring %p at [%lu]\n", iocb, tail);
 
+	if (iocb->ki_signo)
+		__aio_send_signal(iocb->ki_pid, iocb->ki_signo, iocb->ki_notify,
+				  (void*)(unsigned long)iocb->ki_value);
+
 	/* everything turned out well, dispose of the aiocb. */
 	ret = __aio_put_req(ctx, iocb);
 
@@ -994,10 +1046,10 @@ int fastcall io_submit_one(struct kioctx
 	struct file *file;
 	ssize_t ret;
 	char __user *buf;
+	int notify = 0;
 
 	/* enforce forwards compatibility on users */
-	if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2 ||
-		     iocb->aio_reserved3)) {
+	if (unlikely(iocb->aio_reserved1)) {
 		pr_debug("EINVAL: io_submit: reserve field set\n");
 		return -EINVAL;
 	}
@@ -1012,6 +1064,34 @@ int fastcall io_submit_one(struct kioctx
 		return -EINVAL;
 	}
 
+	if (iocb->aio_signo) {
+		pid_t group_id;
+
+		if ( (iocb->aio_lio_opcode != IOCB_CMD_PREAD) &&
+		     (iocb->aio_lio_opcode != IOCB_CMD_PWRITE) )
+			return -EINVAL;
+
+		if (iocb->aio_pid == 0) {
+			/* notify itself */
+
+			iocb->aio_pid = current->pid;
+			notify = IO_NOTIFY_SIGNAL;
+		} else {
+			/* notify given thread */
+
+			/* caller thread and target thread must be in same
+			 * thread group
+			 */
+
+			read_lock(&tasklist_lock);
+			group_id = find_task_by_pid(iocb->aio_pid)->tgid;
+			read_unlock(&tasklist_lock);
+			if (group_id != current->tgid)
+				return -EINVAL;
+			notify = IO_NOTIFY_THREAD_ID;
+		}
+	}
+
 	file = fget(iocb->aio_fildes);
 	if (unlikely(!file))
 		return -EBADF;
@@ -1033,6 +1113,12 @@ int fastcall io_submit_one(struct kioctx
 	req->ki_obj.user = user_iocb;
 	req->ki_user_data = iocb->aio_data;
 	req->ki_pos = iocb->aio_offset;
+	if (iocb->aio_signo) {
+		req->ki_pid = iocb->aio_pid;
+		req->ki_signo = iocb->aio_signo;
+		req->ki_notify = notify;
+		req->ki_value = iocb->aio_value;
+	}
 
 	buf = (char __user *)(unsigned long)iocb->aio_buf;
 
diff -uprN -X dontdiff linux-2.6.8.1/include/linux/aio_abi.h linux-2.6.8.1-aioevent/include/linux/aio_abi.h
--- linux-2.6.8.1/include/linux/aio_abi.h	2004-08-14 12:54:50.000000000 +0200
+++ linux-2.6.8.1-aioevent/include/linux/aio_abi.h	2004-10-21 17:33:43.000000000 +0200
@@ -80,9 +80,10 @@ struct iocb {
 	__u64	aio_nbytes;
 	__s64	aio_offset;
 
-	/* extra parameters */
-	__u64	aio_reserved2;	/* TODO: use this for a (struct sigevent *) */
-	__u64	aio_reserved3;
+	/* event notification */
+	__s32	aio_pid;
+	__s32   aio_signo;
+	__u64	aio_value;
 }; /* 64 bytes */
 
 #undef IFBIG
diff -uprN -X dontdiff linux-2.6.8.1/include/linux/aio.h linux-2.6.8.1-aioevent/include/linux/aio.h
--- linux-2.6.8.1/include/linux/aio.h	2004-08-14 12:54:47.000000000 +0200
+++ linux-2.6.8.1-aioevent/include/linux/aio.h	2004-10-26 11:48:39.000000000 +0200
@@ -7,6 +7,11 @@
 
 #include <asm/atomic.h>
 
+enum {
+	IO_NOTIFY_SIGNAL = 0,		/* send signal to a processe */
+	IO_NOTIFY_THREAD_ID = 1,	/* send signal to a specific thread */
+};
+
 #define AIO_MAXSEGS		4
 #define AIO_KIOGRP_NR_ATOMIC	8
 
@@ -64,6 +69,11 @@ struct kiocb {
 	} ki_obj;
 	__u64			ki_user_data;	/* user's data for completion */
 	loff_t			ki_pos;
+	/* to notify a process on I/O event */
+	__s32			ki_pid;
+	__u16			ki_signo;
+	__u16			ki_notify;
+	__u64			ki_value;
 	void			*private;
 };
 
diff -uprN -X dontdiff linux-2.6.8.1/include/linux/signal.h linux-2.6.8.1-aioevent/include/linux/signal.h
--- linux-2.6.8.1/include/linux/signal.h	2004-08-14 12:54:51.000000000 +0200
+++ linux-2.6.8.1-aioevent/include/linux/signal.h	2004-10-11 10:34:59.000000000 +0200
@@ -211,7 +211,9 @@ static inline void init_sigpending(struc
 	INIT_LIST_HEAD(&sig->list);
 }
 
+extern int __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p);
 extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p);
+extern int specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t);
 extern long do_sigpending(void __user *, unsigned long);
 extern int sigprocmask(int, sigset_t *, sigset_t *);
 
diff -uprN -X dontdiff linux-2.6.8.1/kernel/signal.c linux-2.6.8.1-aioevent/kernel/signal.c
--- linux-2.6.8.1/kernel/signal.c	2004-08-14 12:55:19.000000000 +0200
+++ linux-2.6.8.1-aioevent/kernel/signal.c	2004-10-08 15:51:15.000000000 +0200
@@ -773,7 +773,7 @@ out_set:
 	(((sig) < SIGRTMIN) && sigismember(&(sigptr)->signal, (sig)))
 
 
-static int
+int
 specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
 {
 	int ret = 0;
@@ -963,7 +963,7 @@ __group_complete_signal(int sig, struct 
 	return;
 }
 
-static int
+int
 __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
 {
 	unsigned int mask;
diff -uprN -X dontdiff linux-2.6.8.1/Makefile linux-2.6.8.1-aioevent/Makefile
--- linux-2.6.8.1/Makefile	2004-08-14 12:55:35.000000000 +0200
+++ linux-2.6.8.1-aioevent/Makefile	2004-09-22 16:30:49.000000000 +0200
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 8
-EXTRAVERSION = .1
+EXTRAVERSION = .1-aioevent
 NAME=Zonked Quokka
 
 # *DOCUMENTATION*

