@@ -173,13 +173,12 @@ int lnet_cpt_of_md(struct lnet_libmd *md, unsigned int offset)
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);
@@ -200,7 +199,6 @@ int lnet_cpt_of_md(struct lnet_libmd *md, unsigned int offset)
lmd->md_niov = niov;
INIT_LIST_HEAD(&lmd->md_list);
-
lmd->md_me = NULL;
lmd->md_start = umd->start;
lmd->md_offset = 0;
@@ -238,19 +236,33 @@ int lnet_cpt_of_md(struct lnet_libmd *md, unsigned int offset)
lnet_md_free(lmd);
return ERR_PTR(-EINVAL);
}
- } else { /* contiguous */
- lmd->md_length = umd->length;
- niov = 1;
- lmd->md_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;