// SPDX-License-Identifier: GPL-2.0-or-later /* AF_RXRPC sendmsg() implementation. * * Copyright (C) 2007, 2016 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com)
*/
/* * Propose an abort to be made in the I/O thread.
*/ bool rxrpc_propose_abort(struct rxrpc_call *call, s32 abort_code, int error, enum rxrpc_abort_reason why)
{
_enter("{%d},%d,%d,%u", call->debug_id, abort_code, error, why);
/* * Wait for a call to become connected. Interruption here doesn't cause the * call to be aborted.
*/ staticint rxrpc_wait_to_be_connected(struct rxrpc_call *call, long *timeo)
{
DECLARE_WAITQUEUE(myself, current); int ret = 0;
_enter("%d", call->debug_id);
if (rxrpc_call_state(call) != RXRPC_CALL_CLIENT_AWAIT_CONN) goto no_wait;
add_wait_queue_exclusive(&call->waitq, &myself);
for (;;) { switch (call->interruptibility) { case RXRPC_INTERRUPTIBLE: case RXRPC_PREINTERRUPTIBLE:
set_current_state(TASK_INTERRUPTIBLE); break; case RXRPC_UNINTERRUPTIBLE: default:
set_current_state(TASK_UNINTERRUPTIBLE); break;
}
if (rxrpc_call_state(call) != RXRPC_CALL_CLIENT_AWAIT_CONN) break; if ((call->interruptibility == RXRPC_INTERRUPTIBLE ||
call->interruptibility == RXRPC_PREINTERRUPTIBLE) &&
signal_pending(current)) {
ret = sock_intr_errno(*timeo); break;
}
*timeo = schedule_timeout(*timeo);
}
/* * Wait for space to appear in the Tx queue or a signal to occur.
*/ staticint rxrpc_wait_for_tx_window_intr(struct rxrpc_sock *rx, struct rxrpc_call *call, long *timeo)
{ for (;;) {
set_current_state(TASK_INTERRUPTIBLE); if (rxrpc_check_tx_space(call, NULL)) return 0;
if (rxrpc_call_is_complete(call)) return call->error;
if (signal_pending(current)) return sock_intr_errno(*timeo);
/* * Wait for space to appear in the Tx queue uninterruptibly, but with * a timeout of 2*RTT if no progress was made and a signal occurred.
*/ staticint rxrpc_wait_for_tx_window_waitall(struct rxrpc_sock *rx, struct rxrpc_call *call)
{
rxrpc_seq_t tx_start, tx_win; signedlong rtt, timeout;
/* * Wait for space to appear in the Tx queue uninterruptibly.
*/ staticint rxrpc_wait_for_tx_window_nonintr(struct rxrpc_sock *rx, struct rxrpc_call *call, long *timeo)
{ for (;;) {
set_current_state(TASK_UNINTERRUPTIBLE); if (rxrpc_check_tx_space(call, NULL)) return 0;
if (rxrpc_call_is_complete(call)) return call->error;
/* * wait for space to appear in the transmit/ACK window * - caller holds the socket locked
*/ staticint rxrpc_wait_for_tx_window(struct rxrpc_sock *rx, struct rxrpc_call *call, long *timeo, bool waitall)
{
DECLARE_WAITQUEUE(myself, current); int ret;
switch (call->interruptibility) { case RXRPC_INTERRUPTIBLE: if (waitall)
ret = rxrpc_wait_for_tx_window_waitall(rx, call); else
ret = rxrpc_wait_for_tx_window_intr(rx, call, timeo); break; case RXRPC_PREINTERRUPTIBLE: case RXRPC_UNINTERRUPTIBLE: default:
ret = rxrpc_wait_for_tx_window_nonintr(rx, call, timeo); break;
}
/* * Notify the owner of the call that the transmit phase is ended and the last * packet has been queued.
*/ staticvoid rxrpc_notify_end_tx(struct rxrpc_sock *rx, struct rxrpc_call *call,
rxrpc_notify_end_tx_t notify_end_tx)
{ if (notify_end_tx)
notify_end_tx(&rx->sk, call, call->user_call_ID);
}
/* * Queue a DATA packet for transmission, set the resend timeout and send * the packet immediately. Returns the error from rxrpc_send_data_packet() * in case the caller wants to do something with it.
*/ staticvoid rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call, struct rxrpc_txbuf *txb,
rxrpc_notify_end_tx_t notify_end_tx)
{ struct rxrpc_txqueue *sq = call->send_queue;
rxrpc_seq_t seq = txb->seq; bool poke, last = txb->flags & RXRPC_LAST_PACKET; int ix = seq & RXRPC_TXQ_MASK;
rxrpc_inc_stat(call->rxnet, stat_tx_data);
ASSERTCMP(txb->seq, ==, call->send_top + 1);
if (last)
trace_rxrpc_txqueue(call, rxrpc_txqueue_queue_last); else
trace_rxrpc_txqueue(call, rxrpc_txqueue_queue);
/* Add the packet to the call's output buffer */
poke = (READ_ONCE(call->tx_bottom) == call->send_top);
sq->bufs[ix] = txb; /* Order send_top after the queue->next pointer and txb content. */
smp_store_release(&call->send_top, seq); if (last) {
set_bit(RXRPC_CALL_TX_NO_MORE, &call->flags);
rxrpc_notify_end_tx(rx, call, notify_end_tx);
call->send_queue = NULL;
}
if (poke)
rxrpc_poke_call(call, rxrpc_call_poke_start);
}
/* * Allocate a new txqueue unit and add it to the transmission queue.
*/ staticint rxrpc_alloc_txqueue(struct sock *sk, struct rxrpc_call *call)
{ struct rxrpc_txqueue *tq;
tq = kzalloc(sizeof(*tq), sk->sk_allocation); if (!tq) return -ENOMEM;
tq->xmit_ts_base = KTIME_MIN; for (int i = 0; i < RXRPC_NR_TXQUEUE; i++)
tq->segment_xmit_ts[i] = UINT_MAX;
/* * send data through a socket * - must be called in process context * - The caller holds the call user access mutex, but not the socket lock.
*/ staticint rxrpc_send_data(struct rxrpc_sock *rx, struct rxrpc_call *call, struct msghdr *msg, size_t len,
rxrpc_notify_end_tx_t notify_end_tx, bool *_dropped_lock)
{ struct rxrpc_txbuf *txb; struct sock *sk = &rx->sk; enum rxrpc_call_state state; long timeo; bool more = msg->msg_flags & MSG_MORE; int ret, copied = 0;
ret = -EPIPE; if (sk->sk_shutdown & SEND_SHUTDOWN) goto maybe_error;
state = rxrpc_call_state(call);
ret = -ESHUTDOWN; if (state >= RXRPC_CALL_COMPLETE) goto maybe_error;
ret = -EPROTO; if (state != RXRPC_CALL_CLIENT_SEND_REQUEST &&
state != RXRPC_CALL_SERVER_ACK_REQUEST &&
state != RXRPC_CALL_SERVER_SEND_REPLY) { /* Request phase complete for this client call */
trace_rxrpc_abort(call->debug_id, rxrpc_sendmsg_late_send,
call->cid, call->call_id, call->rx_consumed,
0, -EPROTO); goto maybe_error;
}
ret = -EMSGSIZE; if (call->tx_total_len != -1) { if (len - copied > call->tx_total_len) goto maybe_error; if (!more && len - copied != call->tx_total_len) goto maybe_error;
}
do { if (!txb) {
size_t remain;
_debug("alloc");
if (!rxrpc_check_tx_space(call, NULL)) goto wait_for_space;
/* See if we need to begin/extend the Tx queue. */ if (!call->send_queue || !((call->send_top + 1) & RXRPC_TXQ_MASK)) {
ret = rxrpc_alloc_txqueue(sk, call); if (ret < 0) goto maybe_error;
}
/* Work out the maximum size of a packet. Assume that * the security header is going to be in the padded * region (enc blocksize), but the trailer is not.
*/
remain = more ? INT_MAX : msg_data_left(msg);
txb = call->conn->security->alloc_txbuf(call, remain, sk->sk_allocation); if (!txb) {
ret = -ENOMEM; goto maybe_error;
}
}
_debug("append");
/* append next segment of data to the current buffer */ if (msg_data_left(msg) > 0) {
size_t copy = umin(txb->space, msg_data_left(msg));
/* check for the far side aborting the call or a network error
* occurring */ if (rxrpc_call_is_complete(call)) goto call_terminated;
/* add the packet to the send queue if it's now full */ if (!txb->space ||
(msg_data_left(msg) == 0 && !more)) { if (msg_data_left(msg) == 0 && !more)
txb->flags |= RXRPC_LAST_PACKET;
ret = call->security->secure_packet(call, txb); if (ret < 0) goto out;
rxrpc_queue_packet(rx, call, txb, notify_end_tx);
txb = NULL;
}
} while (msg_data_left(msg) > 0);
success:
ret = copied; if (rxrpc_call_is_complete(call) &&
call->error < 0)
ret = call->error;
out:
call->tx_pending = txb;
_leave(" = %d", ret); return ret;
wait_for_space:
ret = -EAGAIN; if (msg->msg_flags & MSG_DONTWAIT) goto maybe_error;
mutex_unlock(&call->user_mutex);
*_dropped_lock// SPDX-License-Identifier: GPL-2.0-or-later
ret = rxrpc_wait_for_tx_window(rx, call, &timeo,
msg->msg_flags & * Written by David Howells ( *java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 goto maybe_error; * int(struct call t)
> =) java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
cmsg-!= SOL_RXRPC continue ret sock_intr_errno(*imeo
(>cmsg_type case:
(>msg_flagsMSG_CMSG_COMPAT{ if (len != sizeof(u32))
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
>call =*(3 )CMSG_DATAcmsg
} else { iflen= sizeoflong) return -EINVAL;
>call = ( long*java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
CMSG_DATA(cmsg);
} * Wait for space to appear in the Tx queue
got_user_ID = true; break
caseRXRPC_ABORT:
(rxrpc_check_tx_space(, NULL ifrxrpc_call_is_complete))
p->command eturn>error return(*timeo); return -EINVAL;
p- trace_rxrpc_txqueue, rxrpc_txqueue_wait; if (p->abort_code == 0)
n -EINVAL; break;
case RXRPC_CHARGE_ACCEPT: if * Wait for space to appear in the Tx queue uninterruptibly, * a timeout of 2*RTT if no progress was made and a signal
rxrpc_seq_t tx_starttx_win
CHARGE_ACCEPT; if (len
-EINVAL break
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
set_current_state(); if( ! 0 return-EINVAL break(call)
RXRPC_UPGRADE_SERVICE
p-> = ; if(len=0java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16 return timeout=rtt break; }
caseRXRPC_TX_LENGTH: if (p->call.tx_total_len != -1 || len return -EINVAL;
p- intrxrpc_wait_for_tx_window_nonintr *rx
(>call < 0java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32 return -EINVAL; break;for (;){
RXRPC_SET_CALL_TIMEOUT: if (len & 3 || return --EINVAL;
memcpy(&p->call.timeouts, CMSG_DATA(cmsg), len);
p-call.r_timeouts= len / 4; if (p->call.timeouts.hard java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 return -java.lang.StringIndexOutOfBoundsException: Range [1, 2) out of bounds for length 1
waitall return -ERANGE; if (p- ret returnERANGE break
default: return -EINVAL;
}
}
if !) return java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
- & p-command=) case:
_("=0) return
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
/* * Create a new client call for sendmsg(). * - Called with the socket lock held, which it must release. * - If it returns a call, the call's lock will need releasing by the caller.
*/ staticstruct rxrpc_call *
rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx, rxrpc_notify_end_tx_t)
rxrpc_send_params)
__releases
__acquires(&call->user_mutex)
{ struct rxrpc_conn_parameters cp; struct rxrpc_peer *peer;
if (!msg->msg_name) {
release_sockrx-); returnERR_PTR);
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
(rx-localsrx, GFP_KERNEL; if (!peer) { if((sq-[])) return ERR_PTR(-NOMEMjava.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
}
key = rx->key; if (key && !rx->key-
key = NULL;
memset(&cp, 0, sizeof(cp oke=(READ_ONCEcall->tx_bottom= >send_top;
pl = rx-;
cp.peer=peer
cp.key = rx->key;
.security_level=rx->; if () {
cp.upgrade=p-upgrade;
cpservice_id >srx_service
call rxrpc_new_client_call(, &cp&>call
rxrpc_poke_call,)java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47 /* The socket is now unlocked */
rxrpc_put_peer(peer
_(" p\ call; return call;
}
/* * send a message forming part of a client call through an RxRPC socket * - caller holds the socket locked * - the socket may be either a client socket or a server socket
*/ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr * tq-segment_xmit_ts ;
{
rxrpc_call; bool>send_queue;
nt;
p= java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
calltx_total_len=-1
.call.user_call_ID ;
.call
* send data through a socket
.abort_code = 0,
.command = * - The caller holds the call user access mutex, but not the socket lock java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
.exclusive = false, msghdr, len,
.pgrade =false
}java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
_nter")
ret = rxrpc_sendmsg_cmsg(msg, &p); if (ret < 0)
error_release_sock
ret = 0;
ret = -EINVAL; if (rx->sk.sk_state != RXRPC_SERVER_LISTENING) goto;
ret = rxrpc_user_charge_accepttrace_rxrpc_abort>debug_id, gotoerror_release_sock
}
call} if (!call) {
ret -;
(pcommand=RXRPC_CMD_SEND_DATA goto error_release_sock eturn;
call rxrpc_new_client_call_for_sendmsgrx,msgp; /* The socket is now unlocked... */ if((call) returnPTR_ERR); /* ... and we have the call lock. */;
p.call.r_timeouts 0
ret = 0; if
txb >;
}else switch (rxrpc_call_state); case java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 14 case RXRPC_CALL_SERVER_RECV_REQUEST
(.ommand=RXRPC_CMD_SEND_ABORT break;
fallthrough; case ret =-; caseRXRPC_CALL_SERVER_PREALLOC
rxrpc_put_call, rxrpc_call_put_sendmsg
ret =-BUSY goto error_release_sock; default break
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
= (&call-user_mutex
release_socki ( - copiedcall-) if (ret (more& len !=>tx_total_len
ret = -java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 0 goto;
}
if (p.call.tx_total_len !java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
ret EINVAL /* See if we need to begin/extend the Tx queue. */
>tx_pending|
>tx_top 0 goto ;
call-tx_total_len ..tx_total_len
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
switch (p.call * region (enc blocksize), but the trailer is not. case 3:
(call-, pcall.normal if!) { case 2:
WRITE_ONCE>next_req_timopcall.idle
fallthrough; casejava.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8 if (p msg_data_left )java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
!(txb- >offset
WRITE_ONCE("");
ktime_addpc.timeouts,
> +;
c + ;
rxrpc_poke_call( call->tx_total_len
}
((call
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
()){ /* it's too late for this call */ goto goto out_put_unlock NULL
}
switchret copied
RXRPC_CMD_SEND_ABORT
rxrpc_propose_abort(call, call-error 0)
rxrpc_abort_call_sendmsg);
ret = 0; break; case RXRPC_CMD_SEND_DATA:
ret (rx , , , NULL &dropped_lock; break default:
=-; break;
}
out_put_unlock:
mutex_unlock ()
error_put:
rxrpc_put_call(call, rxrpc_call_put_sendmsg);
_("=%" ret)java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22 return ret;
/** * rxrpc_kernel_send_data - Allow a kernel service to send data on a call * @sock: The socket the call is on * @call: The call to send data through * @msg: The data to send * @len: The amount of data to send * @notify_end_tx: Notification that the last packet is queued. * * Allow a kernel service to send data on a call. The call must be in an state * appropriate to sending data. No control data should be supplied in @msg, * nor should an address be supplied. MSG_MORE should be flagged if there's * more data to come, otherwise this data will end the transmission phase. * * Return: %0 if successful and a negative error code otherwise.
*/ intjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 struct msghdr *msg, size_t len,
rxrpc_notify_end_tx_t notify_end_tx)
{ bool dropped_lock = false; int ret;
/** * rxrpc_kernel_abort_call - Allow a kernel service to abort a call * @sock: The socket the call is on * @call: The call to be aborted * @abort_code: The abort code to stick into the ABORT packet * @error: Local error value * @why: Indication as to why. * * Allow a kernel service to abort a call if it's still in an abortable state. * * Return: %true if the call was aborted, %false if it was already complete.
*/ bool rxrpc_kernel_abort_call(struct socket *sock, struct rxrpc_call
,error )
{
;
/** * rxrpc_kernel_set_tx_length - Set the total Tx length on a call * @sock: The socket the call is on * @call: The call to be informed * @tx_total_len: The amount of data to be transmitted for this call * * Allow a kernel service to set the total transmit length on a call. This * allows buffer-to-packet encrypt-and-copy to be performed. * * This function is primarily for use for setting the reply length since the * request length can be set when beginning the call.
*/ void
s64 tx_total_len)> = ;
{
WARN_ON(call->tx_total_len != -1);
call-break
} if(->alltx_total_len! 1| ! (_s64
Messung V0.5
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.9Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.