Whamcloud - gitweb
LU-13805 llite: unaligned direct_rw_pages 93/49993/33
authorPatrick Farrell <pfarrell@whamcloud.com>
Tue, 14 Feb 2023 18:47:54 +0000 (13:47 -0500)
committerOleg Drokin <green@whamcloud.com>
Thu, 28 Sep 2023 07:58:42 +0000 (07:58 +0000)
Add support for ll_direct_rw_pages to handle unaligned
IO by allowing both the first and last page to be partial
pages.

This has been broken off from the main unaligned DIO patch
to make it more reviewable.

Signed-off-by: Patrick Farrell <pfarrell@whamcloud.com>
Change-Id: I055105589d5416fe6aa82fb6a087db7b8b38c8d1
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/49993
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Reviewed-by: Zhenyu Xu <bobijam@hotmail.com>
Reviewed-by: Qian Yingjin <qian@ddn.com>
lustre/llite/rw26.c

index 3a5c85d..ed009f8 100644 (file)
@@ -372,20 +372,23 @@ ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io, size_t size,
        struct cl_sync_io *anchor = &sdio->csd_sync;
        loff_t offset   = pv->ldp_file_offset;
        int io_pages    = 0;
-       int i;
        ssize_t rc = 0;
+       int i = 0;
 
        ENTRY;
 
        cl_2queue_init(queue);
-       for (i = 0; i < pv->ldp_count; i++) {
-               LASSERT(!(offset & (PAGE_SIZE - 1)));
+       while (size > 0) {
+               size_t from = offset & ~PAGE_MASK;
+               size_t to = min(from + size, PAGE_SIZE);
+
                page = cl_page_find(env, obj, offset >> PAGE_SHIFT,
                                    pv->ldp_pages[i], CPT_TRANSIENT);
                if (IS_ERR(page)) {
                        rc = PTR_ERR(page);
                        break;
                }
+
                LASSERT(page->cp_type == CPT_TRANSIENT);
                rc = cl_page_own(env, io, page);
                if (rc) {
@@ -409,16 +412,24 @@ ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io, size_t size,
                 */
                cl_page_list_add(&queue->c2_qin, page, false);
                /*
-                * Set page clip to tell transfer formation engine
-                * that page has to be sent even if it is beyond KMS.
+                * Call page clip for incomplete pages, to set range of bytes
+                * in the page and to tell transfer formation engine to send
+                * the page even if it is beyond KMS (ie, don't trim IO to KMS)
                 */
-               if (size < PAGE_SIZE)
-                       cl_page_clip(env, page, 0, size);
+               if (from != 0 || to != PAGE_SIZE)
+                       cl_page_clip(env, page, from, to);
                ++io_pages;
+               i++;
 
-               offset += PAGE_SIZE;
-               size -= PAGE_SIZE;
+               offset += to - from;
+               size -= to - from;
        }
+       /* on success, we should hit every page in the pvec and have no bytes
+        * left in 'size'
+        */
+       LASSERT(ergo(rc == 0, i == pv->ldp_count));
+       LASSERT(ergo(rc == 0, size == 0));
+
        if (rc == 0 && io_pages > 0) {
                int iot = rw == READ ? CRT_READ : CRT_WRITE;