Whamcloud - gitweb
LU-13004 lnet: always put a page list into struct lnet_libmd 42/37842/5
authorMr NeilBrown <neilb@suse.de>
Tue, 17 Mar 2020 23:00:29 +0000 (10:00 +1100)
committerOleg Drokin <green@whamcloud.com>
Fri, 1 May 2020 04:26:49 +0000 (04:26 +0000)
'struct lnet_libmd' is only created in lnet_md_build().  It can be
given a list of pages or a virtual address.  In the latter case, the
memory will eventually be split into a list of pages.  It is cleaner
to split it into a list of pages early so that all lower levels only
need to handle one type: a page list.

Signed-off-by: Mr NeilBrown <neilb@suse.de>
Change-Id: Iaeb4f18f7ac63986e6fed259945e8594ea1b9f25
Reviewed-on: https://review.whamcloud.com/37842
Reviewed-by: Shaun Tancheff <shaun.tancheff@hpe.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lnet/lnet/lib-md.c

index b46a290..8830820 100644 (file)
@@ -191,13 +191,12 @@ lnet_md_build(struct lnet_md *umd, int unlink)
        struct lnet_libmd *lmd;
        unsigned int size;
 
-       if ((umd->options & LNET_MD_KIOV) != 0) {
+       if (umd->options & LNET_MD_KIOV)
                niov = umd->length;
-               size = offsetof(struct lnet_libmd, md_iov.kiov[niov]);
-       } else {
-               niov = 1;
-               size = offsetof(struct lnet_libmd, md_iov.iov[niov]);
-       }
+       else
+               niov = DIV_ROUND_UP(offset_in_page(umd->start) + umd->length,
+                                   PAGE_SIZE);
+       size = offsetof(struct lnet_libmd, md_iov.kiov[niov]);
 
        if (size <= LNET_SMALL_MD_SIZE) {
                lmd = kmem_cache_zalloc(lnet_small_mds_cachep, GFP_NOFS);
@@ -218,7 +217,6 @@ lnet_md_build(struct lnet_md *umd, int unlink)
 
        lmd->md_niov = niov;
        INIT_LIST_HEAD(&lmd->md_list);
-
        lmd->md_me = NULL;
        lmd->md_start = umd->start;
        lmd->md_offset = 0;
@@ -231,8 +229,7 @@ lnet_md_build(struct lnet_md *umd, int unlink)
        lmd->md_flags = (unlink == LNET_UNLINK) ? LNET_MD_FLAG_AUTO_UNLINK : 0;
        lmd->md_bulk_handle = umd->bulk_handle;
 
-       if ((umd->options & LNET_MD_KIOV) != 0) {
-               lmd->md_niov = niov = umd->length;
+       if (umd->options & LNET_MD_KIOV) {
                memcpy(lmd->md_iov.kiov, umd->start,
                       niov * sizeof(lmd->md_iov.kiov[0]));
 
@@ -255,18 +252,33 @@ lnet_md_build(struct lnet_md *umd, int unlink)
                        lnet_md_free(lmd);
                        return ERR_PTR(-EINVAL);
                }
-       } else {   /* contiguous */
-               lmd->md_length = umd->length;
-               lmd->md_niov = niov = 1;
-               lmd->md_iov.iov[0].iov_base = umd->start;
-               lmd->md_iov.iov[0].iov_len = umd->length;
+       } else {   /* contiguous - split into pages */
+               void *pa = umd->start;
+               int len = umd->length;
 
+               lmd->md_length = len;
+               i = 0;
+               while (len) {
+                       int plen;
+
+                       plen = min_t(int, len, PAGE_SIZE - offset_in_page(pa));
+
+                       lmd->md_iov.kiov[i].bv_page =
+                               lnet_kvaddr_to_page((unsigned long) pa);
+                       lmd->md_iov.kiov[i].bv_offset = offset_in_page(pa);
+                       lmd->md_iov.kiov[i].bv_len = plen;
+
+                       len -= plen;
+                       pa += plen;
+                       i += 1;
+               }
                if ((umd->options & LNET_MD_MAX_SIZE) && /* max size used */
                    (umd->max_size < 0 ||
                     umd->max_size > (int)umd->length)) { /* illegal max_size */
                        lnet_md_free(lmd);
                        return ERR_PTR(-EINVAL);
                }
+               lmd->md_options |= LNET_MD_KIOV;
        }
 
        return lmd;