Skip to content

Commit 0f5c185

Browse files
tonanli66-codegregkh
authored andcommitted
net/rds: handle zerocopy send cleanup before the message is queued
commit 44b550d upstream. A zerocopy send can fail after user pages have been pinned but before the message is attached to the sending socket. The purge path currently infers zerocopy state from rm->m_rs, so an unqueued message can be cleaned up as if it owned normal payload pages. However, zerocopy ownership is really determined by the presence of op_mmp_znotifier, regardless of whether the message has reached the socket queue. Capture op_mmp_znotifier up front in rds_message_purge() and use it as the cleanup discriminator. If the message is already associated with a socket, keep the existing completion path. Otherwise, drop the pinned page accounting directly and release the notifier before putting the payload pages. This keeps early send failure cleanup consistent with the zerocopy lifetime rules without changing the normal queued completion path. Fixes: 0cebacc ("rds: zerocopy Tx support.") Cc: stable@kernel.org Reported-by: Yuan Tan <yuantan098@gmail.com> Reported-by: Yifan Wu <yifanwucs@gmail.com> Reported-by: Juefei Pu <tomapufckgml@gmail.com> Reported-by: Xin Liu <bird@lzu.edu.cn> Co-developed-by: Xiao Liu <lx24@stu.ynu.edu.cn> Signed-off-by: Xiao Liu <lx24@stu.ynu.edu.cn> Signed-off-by: Nan Li <tonanli66@gmail.com> Signed-off-by: Ren Wei <n05ec@lzu.edu.cn> Reviewed-by: Allison Henderson <achender@kernel.org> Link: https://patch.msgid.link/d2ea98a6313d5467bac00f7c9fef8c7acddb9258.1777550074.git.tonanli66@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 40c9cd5 commit 0f5c185

1 file changed

Lines changed: 15 additions & 5 deletions

File tree

net/rds/message.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,24 +131,34 @@ static void rds_rm_zerocopy_callback(struct rds_sock *rs,
131131
*/
132132
static void rds_message_purge(struct rds_message *rm)
133133
{
134+
struct rds_znotifier *znotifier;
134135
unsigned long i, flags;
135-
bool zcopy = false;
136+
bool zcopy;
136137

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

140141
spin_lock_irqsave(&rm->m_rs_lock, flags);
142+
znotifier = rm->data.op_mmp_znotifier;
143+
rm->data.op_mmp_znotifier = NULL;
144+
zcopy = !!znotifier;
145+
141146
if (rm->m_rs) {
142147
struct rds_sock *rs = rm->m_rs;
143148

144-
if (rm->data.op_mmp_znotifier) {
145-
zcopy = true;
146-
rds_rm_zerocopy_callback(rs, rm->data.op_mmp_znotifier);
149+
if (znotifier) {
150+
rds_rm_zerocopy_callback(rs, znotifier);
147151
rds_wake_sk_sleep(rs);
148-
rm->data.op_mmp_znotifier = NULL;
149152
}
150153
sock_put(rds_rs_to_sk(rs));
151154
rm->m_rs = NULL;
155+
} else if (znotifier) {
156+
/*
157+
* Zerocopy can fail before the message is queued on the
158+
* socket, so there is no rs to carry the notification.
159+
*/
160+
mm_unaccount_pinned_pages(&znotifier->z_mmp);
161+
kfree(rds_info_from_znotifier(znotifier));
152162
}
153163
spin_unlock_irqrestore(&rm->m_rs_lock, flags);
154164

0 commit comments

Comments
 (0)