+
+#ifndef __KERNEL__
+#if !defined(kmap)
+#define kmap(page) ((page)->addr)
+#endif
+#if !defined(kunmap)
+#define kunmap(page) do {} while(0)
+#endif
+#if !defined(page_address)
+#define page_address(page) ((page)->page_address)
+#endif
+#endif
+
+ptl_err_t
+lib_lo_rxkiov(lib_nal_t *nal,
+ void *private,
+ lib_msg_t *libmsg,
+ unsigned int niov,
+ ptl_kiov_t *kiov,
+ size_t offset,
+ size_t mlen,
+ size_t rlen)
+{
+ void *srcaddr = NULL;
+ void *dstaddr = NULL;
+ unsigned long srcfrag = 0;
+ unsigned long dstfrag = 0;
+ unsigned long fraglen;
+ lo_desc_t *lod = (lo_desc_t *)private;
+
+ /* I only handle unmapped->unmapped matches */
+ LASSERT(lod->lod_type == LOD_KIOV);
+
+ if (mlen == 0)
+ return PTL_OK;
+
+ while (offset >= kiov->kiov_len) {
+ offset -= kiov->kiov_len;
+ kiov++;
+ niov--;
+ LASSERT(niov > 0);
+ }
+
+ while (lod->lod_offset >= lod->lod_iov.kiov->kiov_len) {
+ lod->lod_offset -= lod->lod_iov.kiov->kiov_len;
+ lod->lod_iov.kiov++;
+ lod->lod_niov--;
+ LASSERT(lod->lod_niov > 0);
+ }
+
+ do {
+ /* CAVEAT EMPTOR:
+ * I kmap 2 pages at once == slight risk of deadlock */
+ LASSERT(niov > 0);
+ if (dstaddr == NULL) {
+ dstaddr = (void *)
+ ((unsigned long)cfs_kmap(kiov->kiov_page) +
+ kiov->kiov_offset + offset);
+ dstfrag = kiov->kiov_len - offset;
+ }
+
+ LASSERT(lod->lod_niov > 0);
+ if (srcaddr == NULL) {
+ srcaddr = (void *)
+ ((unsigned long)cfs_kmap(lod->lod_iov.kiov->kiov_page)+
+ lod->lod_iov.kiov->kiov_offset + lod->lod_offset);
+ srcfrag = lod->lod_iov.kiov->kiov_len - lod->lod_offset;
+ }
+
+ fraglen = MIN(srcfrag, dstfrag);
+ if (fraglen > mlen)
+ fraglen = mlen;
+
+ memcpy(dstaddr, srcaddr, fraglen);
+
+ if (fraglen < dstfrag) {
+ dstfrag -= fraglen;
+ dstaddr = (void *)((unsigned long)dstaddr + fraglen);
+ } else {
+ cfs_kunmap(kiov->kiov_page);
+ dstaddr = NULL;
+ offset = 0;
+ kiov++;
+ niov--;
+ }
+
+ if (fraglen < srcfrag) {
+ srcfrag -= fraglen;
+ srcaddr = (void *)((unsigned long)srcaddr + fraglen);
+ } else {
+ cfs_kunmap(lod->lod_iov.kiov->kiov_page);
+ srcaddr = NULL;
+ lod->lod_offset = 0;
+ lod->lod_iov.kiov++;
+ lod->lod_niov--;
+ }
+
+ mlen -= fraglen;
+ } while (mlen > 0);
+
+ if (dstaddr != NULL)
+ cfs_kunmap(kiov->kiov_page);
+
+ if (srcaddr != NULL)
+ cfs_kunmap(lod->lod_iov.kiov->kiov_page);
+
+ lib_finalize(nal, private, libmsg, PTL_OK);
+ return PTL_OK;
+}
+
+ptl_err_t
+lib_lo_txkiov (lib_nal_t *nal,
+ void *private,
+ lib_msg_t *libmsg,
+ ptl_hdr_t *hdr,
+ int type,
+ ptl_nid_t nid,
+ ptl_pid_t pid,
+ unsigned int payload_niov,
+ ptl_kiov_t *payload_kiov,
+ size_t payload_offset,
+ size_t payload_nob)
+{
+ lo_desc_t lod = {
+ .lod_type = LOD_KIOV,
+ .lod_niov = payload_niov,
+ .lod_offset = payload_offset,
+ .lod_nob = payload_nob,
+ .lod_iov = { .kiov = payload_kiov } };
+ ptl_err_t rc;
+
+ rc = do_lib_parse(nal, hdr, &lod, 1);
+ if (rc == PTL_OK)
+ lib_finalize(nal, private, libmsg, PTL_OK);
+
+ return rc;
+}