mirror of
https://github.com/torvalds/linux.git
synced 2026-10-07 19:16:02 +02:00
smb/server: use MSG_EOR for async interim response
Two kernel_sendmsg() calls can still use the same TCP skb if the first skb
can take more data. This can happen when ksmbd sends two SMB2 responses
very close to each other.
Without MSG_EOR, TCP can append the next sendmsg data to the previous skb.
Then STATUS_PENDING and the later response can be put into the same TCP
skb. MSG_EOR marks the skb as end of record, so TCP will not collapse the
next sendmsg data into it.
Example:
smbtorture //${server_ip}/export -U${username}%${password} smb2.compound_async.write_write
Client request:
Write Request Len:64 Off:0, File: compound_async_write_write; Write Request Len:64 Off:64
Before this patch, server responses:
Write Response, File: compound_async_write_write
Write Response
SMB2, STATUS_PENDING, Write Response, MessageId 7
SMB2, Write Response, MessageId 7
After this patch:
Write Response, File: compound_async_write_write
Write Response, Error: STATUS_PENDING
Write Response
Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
0977715850
commit
49f6a48586
|
|
@ -392,6 +392,15 @@ int ksmbd_conn_write(struct ksmbd_work *work)
|
|||
return __ksmbd_conn_write(work, &tx);
|
||||
}
|
||||
|
||||
int ksmbd_conn_write_eor(struct ksmbd_work *work)
|
||||
{
|
||||
struct ksmbd_transport_write tx = {
|
||||
.msg_flags = MSG_EOR,
|
||||
};
|
||||
|
||||
return __ksmbd_conn_write(work, &tx);
|
||||
}
|
||||
|
||||
int ksmbd_conn_rdma_read(struct ksmbd_conn *conn,
|
||||
void *buf, unsigned int buflen,
|
||||
struct smbdirect_buffer_descriptor_v1 *desc,
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ struct ksmbd_transport_write {
|
|||
int size;
|
||||
bool need_invalidate_rkey;
|
||||
unsigned int remote_key;
|
||||
int msg_flags;
|
||||
};
|
||||
|
||||
struct ksmbd_transport_ops {
|
||||
|
|
@ -182,6 +183,7 @@ int ksmbd_conn_wq_init(void);
|
|||
void ksmbd_conn_wq_destroy(void);
|
||||
bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c);
|
||||
int ksmbd_conn_write(struct ksmbd_work *work);
|
||||
int ksmbd_conn_write_eor(struct ksmbd_work *work);
|
||||
int ksmbd_conn_rdma_read(struct ksmbd_conn *conn,
|
||||
void *buf, unsigned int buflen,
|
||||
struct smbdirect_buffer_descriptor_v1 *desc,
|
||||
|
|
|
|||
|
|
@ -867,7 +867,7 @@ static void smb2_send_interim_compound_prefix(struct ksmbd_work *work)
|
|||
work->conn->ops->set_sign_rsp)
|
||||
work->conn->ops->set_sign_rsp(work);
|
||||
|
||||
err = ksmbd_conn_write(work);
|
||||
err = ksmbd_conn_write_eor(work);
|
||||
if (err)
|
||||
ksmbd_debug(SMB, "failed to send compound interim prefix: %d\n",
|
||||
err);
|
||||
|
|
@ -908,7 +908,7 @@ void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status)
|
|||
smb2_set_err_rsp(in_work);
|
||||
rsp_hdr->Status = status;
|
||||
|
||||
ksmbd_conn_write(in_work);
|
||||
ksmbd_conn_write_eor(in_work);
|
||||
ksmbd_free_work_struct(in_work);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -421,7 +421,7 @@ static int ksmbd_tcp_writev(struct ksmbd_transport *t,
|
|||
const struct ksmbd_transport_write *tx)
|
||||
{
|
||||
struct msghdr smb_msg = {
|
||||
.msg_flags = MSG_NOSIGNAL,
|
||||
.msg_flags = MSG_NOSIGNAL | tx->msg_flags,
|
||||
};
|
||||
|
||||
return kernel_sendmsg(TCP_TRANS(t)->sock, &smb_msg, tx->iov,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user