diff --git a/man/io_uring_get_events.3 b/man/io_uring_get_events.3
new file mode 100644
index 000000000000..2ac3e070473e
--- /dev/null
+++ b/man/io_uring_get_events.3
@@ -0,0 +1,32 @@
+.\" Copyright (C) 2022 Dylan Yudaken
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+.TH io_uring_get_events 3 "September 5, 2022" "liburing-2.3" "liburing Manual"
+.SH NAME
+io_uring_get_events \- Flush outstanding requests to CQE ring
+.SH SYNOPSIS
+.nf
+.B #include <liburing.h>
+.PP
+.BI "int io_uring_get_events(struct io_uring *" ring ");"
+.fi
+.SH DESCRIPTION
+.PP
+The
+.BR io_uring_get_events (3)
+function runs outstanding work and flushes completion events to the CQE ring.
+
+There can be events needing to be flushed if the ring was full and had overflowed.
+Alternatively if the ring was setup with the
+.BR IORING_SETUP_DEFER_TASKRUN
+flag then this will process outstanding tasks, possibly resulting in more CQEs.
+
+.SH RETURN VALUE
+On success
+.BR io_uring_get_events (3)
+returns 0. On failure it returns
+.BR -errno .
+.SH SEE ALSO
+.BR io_uring_get_sqe (3),
+.BR io_uring_submit_and_get_events (3)
diff --git a/man/io_uring_submit_and_get_events.3 b/man/io_uring_submit_and_get_events.3
new file mode 100644
index 000000000000..9e143d1dff47
--- /dev/null
+++ b/man/io_uring_submit_and_get_events.3
@@ -0,0 +1,31 @@
+.\" Copyright (C), 2022  dylany
+.\" You may distribute this file under the terms of the GNU Free
+.\" Documentation License.
+.TH io_uring_submit_and_get_events 3 "September 5, 2022" "liburing-2.3" "liburing Manual"
+.SH NAME
+io_uring_submit_and_get_events \- submit requests to the submission queue and flush completions
+.SH SYNOPSIS
+.nf
+.B #include <liburing.h>
+.PP
+.BI "int io_uring_submit_and_get_events(struct io_uring *" ring ");"
+.fi
+
+.SH DESCRIPTION
+The
+.BR io_uring_submit_and_get_events (3)
+function submits the next events to the submission queue as with
+.BR io_uring_submit (3) .
+After submission it will flush CQEs as with
+.BR io_uring_get_events (3) .
+
+The benefit of this function is that it does both with only one system call.
+
+.SH RETURN VALUE
+On success
+.BR io_uring_submit_and_get_events (3)
+returns the number of submitted submission queue entries. On failure it returns
+.BR -errno .
+.SH SEE ALSO
+.BR io_uring_submit (3),
+.BR io_uring_get_events (3)
diff --git a/src/include/liburing.h b/src/include/liburing.h
index 15e93f5bfb4e..765375cb5c6a 100644
--- a/src/include/liburing.h
+++ b/src/include/liburing.h
@@ -235,6 +235,9 @@ int io_uring_register_sync_cancel(struct io_uring *ring,
 int io_uring_register_file_alloc_range(struct io_uring *ring,
 					unsigned off, unsigned len);
 
+int io_uring_get_events(struct io_uring *ring);
+int io_uring_submit_and_get_events(struct io_uring *ring);
+
 /*
  * io_uring syscalls.
  */
diff --git a/src/liburing.map b/src/liburing.map
index 8573dfc69cf9..5d08857ff906 100644
--- a/src/liburing.map
+++ b/src/liburing.map
@@ -66,4 +66,6 @@ LIBURING_2.3 {
 		io_uring_enter2;
 		io_uring_setup;
 		io_uring_register;
+		io_uring_get_events;
+		io_uring_submit_and_get_events;
 } LIBURING_2.2;
diff --git a/src/queue.c b/src/queue.c
index a670a8ecd20d..b012a3dd950b 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -130,6 +130,15 @@ int __io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr,
 	return _io_uring_get_cqe(ring, cqe_ptr, &data);
 }
 
+int io_uring_get_events(struct io_uring *ring)
+{
+	int flags = IORING_ENTER_GETEVENTS;
+
+	if (ring->int_flags & INT_FLAG_REG_RING)
+		flags |= IORING_ENTER_REGISTERED_RING;
+	return __sys_io_uring_enter(ring->enter_ring_fd, 0, 0, flags, NULL);
+}
+
 /*
  * Fill in an array of IO completions up to count, if any are available.
  * Returns the amount of IO completions filled.
@@ -164,11 +173,7 @@ again:
 		return 0;
 
 	if (cq_ring_needs_flush(ring)) {
-		int flags = IORING_ENTER_GETEVENTS;
-
-		if (ring->int_flags & INT_FLAG_REG_RING)
-			flags |= IORING_ENTER_REGISTERED_RING;
-		__sys_io_uring_enter(ring->enter_ring_fd, 0, 0, flags, NULL);
+		io_uring_get_events(ring);
 		overflow_checked = true;
 		goto again;
 	}
@@ -340,9 +345,9 @@ int io_uring_wait_cqe_timeout(struct io_uring *ring,
  * Returns number of sqes submitted
  */
 static int __io_uring_submit(struct io_uring *ring, unsigned submitted,
-			     unsigned wait_nr)
+			     unsigned wait_nr, bool getevents)
 {
-	bool cq_needs_enter = wait_nr || cq_ring_needs_enter(ring);
+	bool cq_needs_enter = getevents || wait_nr || cq_ring_needs_enter(ring);
 	unsigned flags;
 	int ret;
 
@@ -363,7 +368,7 @@ static int __io_uring_submit(struct io_uring *ring, unsigned submitted,
 
 static int __io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr)
 {
-	return __io_uring_submit(ring, __io_uring_flush_sq(ring), wait_nr);
+	return __io_uring_submit(ring, __io_uring_flush_sq(ring), wait_nr, false);
 }
 
 /*
@@ -386,6 +391,11 @@ int io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr)
 	return __io_uring_submit_and_wait(ring, wait_nr);
 }
 
+int io_uring_submit_and_get_events(struct io_uring *ring)
+{
+	return __io_uring_submit(ring, __io_uring_flush_sq(ring), 0, true);
+}
+
 #ifdef LIBURING_INTERNAL
 struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring)
 {
