net/rds/send.c

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

File Facts

System
Linux kernel
Corpus path
net/rds/send.c
Extension
.c
Size
41615 bytes
Lines
1563
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 (!rm) {
			same_rm = 0;
		} else {
			same_rm++;
			if (same_rm >= 4096) {
				rds_stats_inc(s_send_stuck_rm);
				ret = -EAGAIN;
				break;
			}
		}

		/*
		 * If between sending messages, we can send a pending congestion
		 * map update.
		 */
		if (!rm && test_and_clear_bit(0, &conn->c_map_queued)) {
			rm = rds_cong_update_alloc(conn);
			if (IS_ERR(rm)) {
				ret = PTR_ERR(rm);
				break;
			}
			rm->data.op_active = 1;
			rm->m_inc.i_conn_path = cp;
			rm->m_inc.i_conn = cp->cp_conn;

			cp->cp_xmit_rm = rm;
		}

		/*
		 * If not already working on one, grab the next message.
		 *
		 * cp_xmit_rm holds a ref while we're sending this message down
		 * the connection.  We can use this ref while holding the
		 * send_sem.. rds_send_path_reset() is serialized with it.
		 */
		if (!rm) {
			unsigned int len;

			batch_count++;

			/* we want to process as big a batch as we can, but
			 * we also want to avoid softlockups.  If we've been
			 * through a lot of messages, lets back off and see
			 * if anyone else jumps in
			 */
			if (batch_count >= send_batch_count)
				goto over_batch;

			/* make sure cp_index#0 caught up during fan-out in
			 * order to avoid lane races
			 */
			if (cp->cp_index > 0 && rds_mprds_cp0_catchup(conn)) {
				rds_stats_inc(s_mprds_catchup_tx0_retries);
				goto over_batch;
			}

			spin_lock_irqsave(&cp->cp_lock, flags);

			if (!list_empty(&cp->cp_send_queue)) {
				rm = list_entry(cp->cp_send_queue.next,
						struct rds_message,
						m_conn_item);
				rds_message_addref(rm);

				/*
				 * Move the message from the send queue to the retransmit
				 * list right away.
				 */
				list_move_tail(&rm->m_conn_item,
					       &cp->cp_retrans);
			}

			spin_unlock_irqrestore(&cp->cp_lock, flags);

			if (!rm)
				break;

			/* Unfortunately, the way Infiniband deals with
			 * RDMA to a bad MR key is by moving the entire
			 * queue pair to error state. We could possibly
			 * recover from that, but right now we drop the
			 * connection.
			 * Therefore, we never retransmit messages with RDMA ops.
			 */
			if (test_bit(RDS_MSG_FLUSH, &rm->m_flags) ||
			    (rm->rdma.op_active &&
			    test_bit(RDS_MSG_RETRANSMITTED, &rm->m_flags))) {
				spin_lock_irqsave(&cp->cp_lock, flags);
				if (test_and_clear_bit(RDS_MSG_ON_CONN, &rm->m_flags))
					list_move(&rm->m_conn_item, &to_be_dropped);

Annotation

Implementation Notes