History

mm: add support for async page locking

Normally waiting for a page to become unlocked, or locking the page, requires waiting for IO to complete. Add support for lock_page_async() and wait_on_page_locked_async(), which are callback based instead. This allows a caller to get notified when a page becomes unlocked, rather than wait for it. We add a new iocb field, ki_waitq, to pass in the necessary data for this to happen. We can unionize this with ki_cookie, since that is only used for polled IO. Polled IO can never co-exist with async callbacks, as it is (by definition) polled completions. struct wait_page_key is made public, and we define struct wait_page_async as the interface between the caller and the core.

Jens Axboe committed 6 years ago

Commit dd3e6d51 parent c7510ab3 files · +67 −2Browse files

Showing the changes to include/linux (2 of 3 files). Show all

Unified · Split

2 files
  1. include/linux/fs.h +6 −1
  2. include/linux/pagemap.h +17 −0
include/linux/fs.h+6−1
@@ -315,6 +315,8 @@ enum rw_hint { · 314 unmodified lines
315315 #define IOCB_SYNC (1 << 5)
316316 #define IOCB_WRITE (1 << 6)
317317 #define IOCB_NOWAIT (1 << 7)
318+/* iocb->ki_waitq is valid */
319+#define IOCB_WAITQ (1 << 8)
318320
319321 struct kiocb {
320322 struct file *ki_filp;
@@ -328,7 +330,10 @@ struct kiocb { · 7 unmodified lines
328330 int ki_flags;
329331 u16 ki_hint;
330332 u16 ki_ioprio; /* See linux/ioprio.h */
331− unsigned int ki_cookie; /* for ->iopoll */
333+ union {
334+ unsigned int ki_cookie; /* for ->iopoll */
335+ struct wait_page_queue *ki_waitq; /* for async buffered IO */
336+ };
332337
333338 randomized_struct_fields_end
334339 };
include/linux/pagemap.h+17−0
@@ -535,6 +535,7 @@ static inline int wake_page_match(struct wait_page_queue *wait_page, · 534 unmodified lines
535535
536536 extern void __lock_page(struct page *page);
537537 extern int __lock_page_killable(struct page *page);
538+extern int __lock_page_async(struct page *page, struct wait_page_queue *wait);
538539 extern int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
539540 unsigned int flags);
540541 extern void unlock_page(struct page *page);
@@ -571,6 +572,22 @@ static inline int lock_page_killable(struct page *page) · 30 unmodified lines
571572 return 0;
572573 }
573574
575+/*
576+ * lock_page_async - Lock the page, unless this would block. If the page
577+ * is already locked, then queue a callback when the page becomes unlocked.
578+ * This callback can then retry the operation.
579+ *
580+ * Returns 0 if the page is locked successfully, or -EIOCBQUEUED if the page
581+ * was already locked and the callback defined in 'wait' was queued.
582+ */
583+static inline int lock_page_async(struct page *page,
584+ struct wait_page_queue *wait)
585+{
586+ if (!trylock_page(page))
587+ return __lock_page_async(page, wait);
588+ return 0;
589+}
590+
574591 /*
575592 * lock_page_or_retry - Lock the page, unless this would block and the
576593 * caller indicated that it can handle a retry.