- const int max_size_opts = PTL_MD_AUTO_UNLINK |
- PTL_MD_MAX_SIZE;
- lib_eq_t *eq = NULL;
- int rc;
- int i;
-
- /* NB we are passes an allocated, but uninitialised/active md.
- * if we return success, caller may lib_md_unlink() it.
- * otherwise caller may only lib_md_free() it.
- */
-
- if (!PtlHandleEqual (*eqh, PTL_EQ_NONE)) {
- eq = ptl_handle2eq(eqh, nal);
- if (eq == NULL)
- return PTL_INV_EQ;
- }
-
- if ((md->options & PTL_MD_IOV) != 0 && /* discontiguous MD */
- md->niov > PTL_MD_MAX_IOV) /* too many fragments */
- return PTL_IOV_TOO_MANY;
-
- if ((md->options & max_size_opts) != 0 && /* max size used */
- (md->max_size < 0 || md->max_size > md->length)) // illegal max_size
- return PTL_INV_MD;
-
- new->me = NULL;
- new->start = md->start;
- new->length = md->length;
- new->offset = 0;
- new->max_size = md->max_size;
- new->unlink = unlink;
- new->options = md->options;
- new->user_ptr = md->user_ptr;
- new->eq = eq;
- new->threshold = md->threshold;
- new->pending = 0;
- new->md_flags = 0;
-
- if ((md->options & PTL_MD_IOV) != 0) {
- int total_length = 0;
-
- if ((md->options & PTL_MD_KIOV) != 0) /* Can't specify both */
- return PTL_INV_MD;
-
- new->md_niov = md->niov;
-
- if (nal->cb_read (nal, private, new->md_iov.iov, md->start,
- md->niov * sizeof (new->md_iov.iov[0])))
- return PTL_SEGV;
-
- for (i = 0; i < new->md_niov; i++) {
- /* We take the base address on trust */
- if (new->md_iov.iov[i].iov_len <= 0) /* invalid length */
- return PTL_VAL_FAILED;
-
- total_length += new->md_iov.iov[i].iov_len;
- }
-
- if (md->length > total_length)
- return PTL_IOV_TOO_SMALL;
-
- if (nal->cb_map != NULL) {
- rc = nal->cb_map (nal, new->md_niov, new->md_iov.iov,
- &new->md_addrkey);
- if (rc != PTL_OK)
- return (rc);
- }
- } else if ((md->options & PTL_MD_KIOV) != 0) {
-#ifndef __KERNEL__
- return PTL_INV_MD;
-#else
- int total_length = 0;
-
- /* Trap attempt to use paged I/O if unsupported early. */
- if (nal->cb_send_pages == NULL ||
- nal->cb_recv_pages == NULL)
- return PTL_INV_MD;
-
- new->md_niov = md->niov;
-
- if (nal->cb_read (nal, private, new->md_iov.kiov, md->start,
- md->niov * sizeof (new->md_iov.kiov[0])))
- return PTL_SEGV;
-
- for (i = 0; i < new->md_niov; i++) {
- /* We take the page pointer on trust */
- if (new->md_iov.kiov[i].kiov_offset +
- new->md_iov.kiov[i].kiov_len > PAGE_SIZE )
- return PTL_VAL_FAILED; /* invalid length */
-
- total_length += new->md_iov.kiov[i].kiov_len;
- }
-
- if (md->length > total_length)
- return PTL_IOV_TOO_SMALL;
-
- if (nal->cb_map_pages != NULL) {
- rc = nal->cb_map_pages (nal, new->md_niov, new->md_iov.kiov,
- &new->md_addrkey);
- if (rc != PTL_OK)
- return (rc);
- }
-#endif
- } else { /* contiguous */
- new->md_niov = 1;
- new->md_iov.iov[0].iov_base = md->start;
- new->md_iov.iov[0].iov_len = md->length;
-
- if (nal->cb_map != NULL) {
- rc = nal->cb_map (nal, new->md_niov, new->md_iov.iov,
- &new->md_addrkey);
- if (rc != PTL_OK)
- return (rc);
- }
- }
-
- if (eq != NULL)
- eq->eq_refcount++;
-
- /* It's good; let handle2md succeed and add to active mds */
- lib_initialise_handle (nal, &new->md_lh, PTL_COOKIE_TYPE_MD);
- list_add (&new->md_list, &nal->ni.ni_active_mds);
-
- return PTL_OK;
+ int i;
+ unsigned int niov;
+ int total_length = 0;
+
+ lmd->md_me = NULL;
+ lmd->md_start = umd->start;
+ lmd->md_offset = 0;
+ lmd->md_max_size = umd->max_size;
+ lmd->md_options = umd->options;
+ lmd->md_user_ptr = umd->user_ptr;
+ lmd->md_eq = NULL;
+ lmd->md_threshold = umd->threshold;
+ lmd->md_refcount = 0;
+ lmd->md_flags = (unlink == LNET_UNLINK) ? LNET_MD_FLAG_AUTO_UNLINK : 0;
+
+ if ((umd->options & LNET_MD_IOVEC) != 0) {
+
+ if ((umd->options & LNET_MD_KIOV) != 0) /* Can't specify both */
+ return -EINVAL;
+
+ lmd->md_niov = niov = umd->length;
+ memcpy(lmd->md_iov.iov, umd->start,
+ niov * sizeof(lmd->md_iov.iov[0]));
+
+ for (i = 0; i < (int)niov; i++) {
+ /* We take the base address on trust */
+ if (lmd->md_iov.iov[i].iov_len <= 0) /* invalid length */
+ return -EINVAL;
+
+ total_length += lmd->md_iov.iov[i].iov_len;
+ }
+
+ lmd->md_length = total_length;
+
+ if ((umd->options & LNET_MD_MAX_SIZE) != 0 && /* max size used */
+ (umd->max_size < 0 ||
+ umd->max_size > total_length)) // illegal max_size
+ return -EINVAL;
+
+ } else if ((umd->options & LNET_MD_KIOV) != 0) {
+ lmd->md_niov = niov = umd->length;
+ memcpy(lmd->md_iov.kiov, umd->start,
+ niov * sizeof(lmd->md_iov.kiov[0]));
+
+ for (i = 0; i < (int)niov; i++) {
+ /* We take the page pointer on trust */
+ if (lmd->md_iov.kiov[i].kiov_offset +
+ lmd->md_iov.kiov[i].kiov_len > PAGE_SIZE)
+ return -EINVAL; /* invalid length */
+
+ total_length += lmd->md_iov.kiov[i].kiov_len;
+ }
+
+ lmd->md_length = total_length;
+
+ if ((umd->options & LNET_MD_MAX_SIZE) != 0 && /* max size used */
+ (umd->max_size < 0 ||
+ umd->max_size > total_length)) // illegal max_size
+ return -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;
+
+ if ((umd->options & LNET_MD_MAX_SIZE) != 0 && /* max size used */
+ (umd->max_size < 0 ||
+ umd->max_size > (int)umd->length)) // illegal max_size
+ return -EINVAL;
+ }
+
+ return 0;