net/rds/rdma.c

Source file repositories/reference/linux-study-clean/net/rds/rdma.c

File Facts

System
Linux kernel
Corpus path
net/rds/rdma.c
Extension
.c
Size
25606 bytes
Lines
955
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!sg) {
			ret = -ENOMEM;
			goto out;
		}
		WARN_ON(!nents);
		sg_init_table(sg, nents);

		/* Stick all pages into the scatterlist */
		for (i = 0 ; i < nents; i++)
			sg_set_page(&sg[i], pages[i], PAGE_SIZE, 0);

		rdsdebug("RDS: trans_private nents is %u\n", nents);
	}
	/* Obtain a transport specific MR. If this succeeds, the
	 * s/g list is now owned by the MR.
	 * Note that dma_map() implies that pending writes are
	 * flushed to RAM, so no dma_sync is needed here. */
	trans_private = rs->rs_transport->get_mr(
		sg, nents, rs, &mr->r_key, cp ? cp->cp_conn : NULL,
		args->vec.addr, args->vec.bytes,
		need_odp ? ODP_ZEROBASED : ODP_NOT_NEEDED);

	if (IS_ERR(trans_private)) {
		/* In ODP case, we don't GUP pages, so don't need
		 * to release anything.
		 */
		if (!need_odp) {
			unpin_user_pages(pages, nr_pages);
			kfree(sg);
		}
		ret = PTR_ERR(trans_private);
		/* Trigger connection so that its ready for the next retry */
		if (ret == -ENODEV && cp)
			rds_conn_connect_if_down(cp->cp_conn);
		goto out;
	}

	mr->r_trans_private = trans_private;

	rdsdebug("RDS: get_mr put_user key is %x cookie_addr %p\n",
	       mr->r_key, (void *)(unsigned long) args->cookie_addr);

	/* The user may pass us an unaligned address, but we can only
	 * map page aligned regions. So we keep the offset, and build
	 * a 64bit cookie containing <R_Key, offset> and pass that
	 * around. */
	if (need_odp)
		cookie = rds_rdma_make_cookie(mr->r_key, 0);
	else
		cookie = rds_rdma_make_cookie(mr->r_key,
					      args->vec.addr & ~PAGE_MASK);
	if (cookie_ret)
		*cookie_ret = cookie;

	if (args->cookie_addr &&
	    put_user(cookie, (u64 __user *)(unsigned long)args->cookie_addr)) {
		ret = -EFAULT;
		goto out;
	}

	/* Inserting the new MR into the rbtree bumps its
	 * reference count. */
	spin_lock_irqsave(&rs->rs_rdma_lock, flags);
	found = rds_mr_tree_walk(&rs->rs_rdma_keys, mr->r_key, mr);
	spin_unlock_irqrestore(&rs->rs_rdma_lock, flags);

	BUG_ON(found && found != mr);

	rdsdebug("RDS: get_mr key is %x\n", mr->r_key);
	if (mr_ret) {
		kref_get(&mr->r_kref);
		*mr_ret = mr;
	}

	ret = 0;
out:
	kfree(pages);
	if (mr)
		kref_put(&mr->r_kref, __rds_put_mr_final);
	return ret;
}

int rds_get_mr(struct rds_sock *rs, sockptr_t optval, int optlen)
{
	struct rds_get_mr_args args;

	if (optlen != sizeof(struct rds_get_mr_args))
		return -EINVAL;

	if (copy_from_sockptr(&args, optval, sizeof(struct rds_get_mr_args)))

Annotation

Implementation Notes