net/rds/message.c

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

File Facts

System
Linux kernel
Corpus path
net/rds/message.c
Extension
.c
Size
15004 bytes
Lines
571
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration 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 (rds_zcookie_add(info, cookie)) {
			spin_unlock_irqrestore(&q->lock, flags);
			kfree(rds_info_from_znotifier(znotif));
			/* caller invokes rds_wake_sk_sleep() */
			return;
		}
	}

	info = rds_info_from_znotifier(znotif);
	ck = &info->zcookies;
	memset(ck, 0, sizeof(*ck));
	WARN_ON(!rds_zcookie_add(info, cookie));
	list_add_tail(&info->rs_zcookie_next, &q->zcookie_head);

	spin_unlock_irqrestore(&q->lock, flags);
	/* caller invokes rds_wake_sk_sleep() */
}

/*
 * This relies on dma_map_sg() not touching sg[].page during merging.
 */
static void rds_message_purge(struct rds_message *rm)
{
	struct rds_znotifier *znotifier;
	unsigned long i, flags;
	bool zcopy;

	if (unlikely(test_bit(RDS_MSG_PAGEVEC, &rm->m_flags)))
		return;

	spin_lock_irqsave(&rm->m_rs_lock, flags);
	znotifier = rm->data.op_mmp_znotifier;
	rm->data.op_mmp_znotifier = NULL;
	zcopy = !!znotifier;

	if (rm->m_rs) {
		struct rds_sock *rs = rm->m_rs;

		if (znotifier) {
			rds_rm_zerocopy_callback(rs, znotifier);
			rds_wake_sk_sleep(rs);
		}
		sock_put(rds_rs_to_sk(rs));
		rm->m_rs = NULL;
	} else if (znotifier) {
		/*
		 * Zerocopy can fail before the message is queued on the
		 * socket, so there is no rs to carry the notification.
		 */
		mm_unaccount_pinned_pages(&znotifier->z_mmp);
		kfree(rds_info_from_znotifier(znotifier));
	}
	spin_unlock_irqrestore(&rm->m_rs_lock, flags);

	for (i = 0; i < rm->data.op_nents; i++) {
		/* XXX will have to put_page for page refs */
		if (!zcopy)
			__free_page(sg_page(&rm->data.op_sg[i]));
		else
			put_page(sg_page(&rm->data.op_sg[i]));
	}
	rm->data.op_nents = 0;

	if (rm->rdma.op_active)
		rds_rdma_free_op(&rm->rdma);
	if (rm->rdma.op_rdma_mr)
		kref_put(&rm->rdma.op_rdma_mr->r_kref, __rds_put_mr_final);

	if (rm->atomic.op_active)
		rds_atomic_free_op(&rm->atomic);
	if (rm->atomic.op_rdma_mr)
		kref_put(&rm->atomic.op_rdma_mr->r_kref, __rds_put_mr_final);
}

void rds_message_put(struct rds_message *rm)
{
	rdsdebug("put rm %p ref %d\n", rm, refcount_read(&rm->m_refcount));
	WARN(!refcount_read(&rm->m_refcount), "danger refcount zero on %p\n", rm);
	if (refcount_dec_and_test(&rm->m_refcount)) {
		BUG_ON(!list_empty(&rm->m_sock_item));
		BUG_ON(!list_empty(&rm->m_conn_item));
		rds_message_purge(rm);

		kfree(rm);
	}
}
EXPORT_SYMBOL_GPL(rds_message_put);

void rds_message_populate_header(struct rds_header *hdr, __be16 sport,
				 __be16 dport, u64 seq)

Annotation

Implementation Notes