diff -uprN -X dontdiff linux-2.6.8.1-lioevent/fs/aio.c linux-2.6.8.1-liowait/fs/aio.c
--- linux-2.6.8.1-lioevent/fs/aio.c	2004-11-05 16:02:19.000000000 +0100
+++ linux-2.6.8.1-liowait/fs/aio.c	2004-11-05 18:09:42.388106513 +0100
@@ -452,8 +452,8 @@ static inline void really_put_req(struct
 	req->ki_pid = 0;
 	req->ki_signo = 0;
 	req->ki_notify = 0;
-	req->private = NULL;
 	req->ki_lio_event = NULL;
+	req->private = NULL;
 	kmem_cache_free(kiocb_cachep, req);
 	ctx->reqs_active--;
 
@@ -676,6 +676,60 @@ static void __aio_send_signal(pid_t pid,
 	read_unlock(&tasklist_lock);
 }
 
+static void wait_for_lio(struct kioctx *ctx, struct lio_event *lio)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	add_wait_queue(&ctx->wait, &wait);
+	set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+
+	while ( atomic_read(&lio->lio_users) ) {
+		schedule();
+		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+	}
+	__set_task_state(tsk, TASK_RUNNING);
+	remove_wait_queue(&ctx->wait, &wait);
+}
+
+static inline void check_lio(struct kioctx *ctx, 
+			     struct lio_event *lio, int wait)
+{
+	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);
+		}
+
+	} else if (wait) {
+
+		/* if needed, wait end of all AIO of this list */
+
+		wait_for_lio(ctx, lio);
+
+		/* free memory */
+
+		kfree(lio);
+	}
+}
+
 /* 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 
@@ -757,23 +811,7 @@ int fastcall aio_complete(struct kiocb *
 		__aio_send_signal(iocb->ki_pid, iocb->ki_signo, iocb->ki_notify,
 				  (void*)(unsigned long)iocb->ki_value);
 
-	if (iocb->ki_lio_event) {
-		/* decrement and test users counter */
-
-		ret = atomic_dec_and_test(&iocb->ki_lio_event->lio_users);
-
-		if (likely(ret)) {
-			/* last one -> notify process */
-
-			if (iocb->ki_lio_event->lio_signo)
-				__aio_send_signal(iocb->ki_lio_event->lio_pid,
-						 iocb->ki_lio_event->lio_signo,
-						 iocb->ki_lio_event->lio_notify,
-						(void*)(unsigned long)iocb->ki_lio_event->lio_value);
-
-			kfree(iocb->ki_lio_event);
-		}
-	}
+	check_lio(ctx, iocb->ki_lio_event, 0);
 
 	/* everything turned out well, dispose of the aiocb. */
 	ret = __aio_put_req(ctx, iocb);
@@ -1059,8 +1097,44 @@ asmlinkage long sys_io_destroy(aio_conte
 	return -EINVAL;
 }
 
-static int create_lio_event(struct lio_event **lio, pid_t pid, int signo, 
-			    void *value)
+static int create_lio_wait(struct kioctx *ctx, struct lio_event **lio,
+			    int enable)
+{
+	if (*lio != NULL) {
+
+		/* we break an existing sequence (lio exists)
+		 * close the sequence
+		 */
+
+		check_lio(ctx, *lio, 1);
+		*lio = NULL;
+	}
+
+	if (!enable) {
+
+		/* it means we don't want to monitor following commands
+		 * usefull to break current sequence
+		 */
+
+		return 0;
+	}
+
+
+	*lio = kmalloc(sizeof(*lio), GFP_KERNEL);
+	if (!*lio)
+		return -EAGAIN;
+
+	atomic_set(&((*lio)->lio_users), 1);
+	(*lio)->lio_pid = 0;
+	(*lio)->lio_signo = 0;
+	(*lio)->lio_notify = 0;
+	(*lio)->lio_value = 0;
+
+	return 0;
+}
+
+static int create_lio_event(struct kioctx *ctx, struct lio_event **lio,
+			    pid_t pid, int signo, void *value)
 {
 	int notify;
 
@@ -1086,23 +1160,11 @@ static int create_lio_event(struct lio_e
 		notify = IO_NOTIFY_THREAD_ID;
 	}
 
-	if (*lio != NULL) {
-		int ret;
+	/* we break an existing sequence (lio exists)
+	 * close the sequence
+	 */
 
-		/* we break an existing sequence (lio exists)
-		 * close the sequence
-		 */
-
-		ret = atomic_dec_and_test(&((*lio)->lio_users));
-		if (likely(ret)) {
-			if ((*lio)->lio_signo)
-				__aio_send_signal((*lio)->lio_pid, 
-						  (*lio)->lio_signo, 
-					  	  (*lio)->lio_notify,
-						  (void*)(unsigned long)(*lio)->lio_value);
-			kfree(*lio);
-		}
-	}
+	check_lio(ctx, *lio, 1);
 
 	if (signo == 0) {
 
@@ -1111,7 +1173,6 @@ static int create_lio_event(struct lio_e
 		 */
 
 		*lio = NULL;
-
 		return 0;
 	}
 
@@ -1323,7 +1384,30 @@ asmlinkage long sys_io_submit(aio_contex
 			break;
 		}
 
-		if (tmp.aio_lio_opcode == IOCB_CMD_EVENT) {
+		if (tmp.aio_lio_opcode == IOCB_CMD_CHECKPOINT) {
+			/* this command means that all following IO commands
+			 * are in the same group.
+			 * io_submit() will wait all commands of the group
+			 * have been processed before exiting.
+			 */
+
+			if (tmp.aio_pid) {
+				ret = -EINVAL;
+				break;
+			}
+
+			if ( (tmp.aio_signo != 0) && (tmp.aio_signo != 1) ) {
+				ret = -EINVAL;
+				break;
+			}
+
+			ret = create_lio_wait(ctx, &lio, tmp.aio_signo);
+			if (ret)
+				break;
+
+			continue;
+
+		} else 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
@@ -1331,7 +1415,7 @@ asmlinkage long sys_io_submit(aio_contex
 			 * we must send a signal to a given process or thread
 			 */
 
-			ret = create_lio_event(&lio,
+			ret = create_lio_event(ctx, &lio,
 					       tmp.aio_pid, tmp.aio_signo,
 					       user_iocb);
 			if (ret)
@@ -1356,19 +1440,7 @@ asmlinkage long sys_io_submit(aio_contex
 				break;
 		}
 	}
-	if (lio) {
-
-		/* close the sequence */
-
-		ret = atomic_dec_and_test(&lio->lio_users);
-		if (likely(ret)) {
-			if (lio->lio_signo)
-				__aio_send_signal(lio->lio_pid, lio->lio_signo, 
-						  lio->lio_notify, 
-						  (void*)(unsigned long)lio->lio_value);
-			kfree(lio);
-		}
-	}
+	check_lio(ctx, lio, 1);
 
 	put_ioctx(ctx);
 	return i ? i : ret;
diff -uprN -X dontdiff linux-2.6.8.1-lioevent/include/linux/aio_abi.h linux-2.6.8.1-liowait/include/linux/aio_abi.h
--- linux-2.6.8.1-lioevent/include/linux/aio_abi.h	2004-11-05 16:02:19.000000000 +0100
+++ linux-2.6.8.1-liowait/include/linux/aio_abi.h	2004-11-03 11:30:55.000000000 +0100
@@ -42,6 +42,7 @@ enum {
 	 */
 	IOCB_CMD_NOOP = 6,
 	IOCB_CMD_EVENT = 7,
+	IOCB_CMD_CHECKPOINT = 8,
 };
 
 /* read() from /dev/aio returns these structures. */

