* [PATCH net] net/rds: fix zerocopy page ownership on partial copy failure
@ 2026-05-10 21:20 Spencer ??
2026-05-12 0:17 ` Jakub Kicinski
0 siblings, 1 reply; 2+ messages in thread
From: Spencer ?? @ 2026-05-10 21:20 UTC (permalink / raw)
To: Allison Henderson, netdev@vger.kernel.org
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, linux-rdma@vger.kernel.org,
rds-devel@oss.oracle.com, linux-kernel@vger.kernel.org
RDS zerocopy sends pin user pages into the message data SG list and uses a
zerocopy notifier to carry pin accounting and completion state.
If iov_iter_get_pages2() fails after some SG entries have already been
populated, the copy helper currently tears down the notifier and returns an
error while leaving the partial SG count live.
The common message purge path no longer has a notifier to distinguish
zerocopy user pages from copied-send pages in that state, so it can release
a still-mapped user page with __free_page().
Make data page ownership explicit with an op_zcopy bit. Once zerocopy pin
accounting succeeds, leave the notifier, ownership bit, and populated SG
count attached to the message and let rds_message_purge() perform the
single cleanup path.
The notifier still controls zerocopy completion and pin accounting. The new
op_zcopy bit controls whether counted data SG entries are released with
put_page() or __free_page().
This preserves normal copied-send cleanup and queued zerocopy completion
behavior. It fixes the partial-build failure path without adding a second
manual unwind path.
Tested with an AF_RDS/RDS_TCP MSG_ZEROCOPY partial-fault reproducer on a
KASAN kernel. Before the fix the run triggered bad page/accounting reports;
after the fix sendmsg returns -EFAULT and no bad page or KASAN report occurs.
Fixes: 0cebaccef3ac ("rds: zerocopy Tx support.")
Cc: stable@vger.kernel.org
Assisted-By: Codex:GPT-5.5-xhigh
Signed-off-by: Spencer Phillips <spencer.phillips@live.com>
---
net/rds/message.c | 33 ++++++++++-----------------------
net/rds/rds.h | 1 +
2 files changed, 11 insertions(+), 23 deletions(-)
diff --git a/net/rds/message.c b/net/rds/message.c
index 25fedcb3cd00..a381a895339c 100644
--- a/net/rds/message.c
+++ b/net/rds/message.c
@@ -141,7 +141,7 @@ static void rds_message_purge(struct rds_message *rm)
spin_lock_irqsave(&rm->m_rs_lock, flags);
znotifier = rm->data.op_mmp_znotifier;
rm->data.op_mmp_znotifier = NULL;
- zcopy = !!znotifier;
+ zcopy = rm->data.op_zcopy || !!znotifier;
if (rm->m_rs) {
struct rds_sock *rs = rm->m_rs;
@@ -170,6 +170,7 @@ static void rds_message_purge(struct rds_message *rm)
put_page(sg_page(&rm->data.op_sg[i]));
}
rm->data.op_nents = 0;
+ rm->data.op_zcopy = 0;
if (rm->rdma.op_active)
rds_rdma_free_op(&rm->rdma);
@@ -414,7 +415,6 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in
static int rds_message_zcopy_from_user(struct rds_message *rm, struct iov_iter *from)
{
struct scatterlist *sg;
- int ret = 0;
int length = iov_iter_count(from);
struct rds_msg_zcopy_info *info;
@@ -429,12 +429,12 @@ static int rds_message_zcopy_from_user(struct rds_message *rm, struct iov_iter *
if (!info)
return -ENOMEM;
INIT_LIST_HEAD(&info->rs_zcookie_next);
- rm->data.op_mmp_znotifier = &info->znotif;
- if (mm_account_pinned_pages(&rm->data.op_mmp_znotifier->z_mmp,
- length)) {
- ret = -ENOMEM;
- goto err;
+ if (mm_account_pinned_pages(&info->znotif.z_mmp, length)) {
+ kfree(info);
+ return -ENOMEM;
}
+ rm->data.op_mmp_znotifier = &info->znotif;
+ rm->data.op_zcopy = 1;
while (iov_iter_count(from)) {
struct page *pages;
size_t start;
@@ -442,28 +442,15 @@ static int rds_message_zcopy_from_user(struct rds_message *rm, struct iov_iter *
copied = iov_iter_get_pages2(from, &pages, PAGE_SIZE,
1, &start);
- if (copied < 0) {
- struct mmpin *mmp;
- int i;
-
- for (i = 0; i < rm->data.op_nents; i++)
- put_page(sg_page(&rm->data.op_sg[i]));
- mmp = &rm->data.op_mmp_znotifier->z_mmp;
- mm_unaccount_pinned_pages(mmp);
- ret = -EFAULT;
- goto err;
- }
+ if (copied < 0)
+ return -EFAULT;
length -= copied;
sg_set_page(sg, pages, copied, start);
rm->data.op_nents++;
sg++;
}
WARN_ON_ONCE(length != 0);
- return ret;
-err:
- kfree(info);
- rm->data.op_mmp_znotifier = NULL;
- return ret;
+ return 0;
}
int rds_message_copy_from_user(struct rds_message *rm, struct iov_iter *from,
diff --git a/net/rds/rds.h b/net/rds/rds.h
index 6e0790e4b570..b27848ec5c5a 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -496,6 +496,7 @@ struct rds_message {
} rdma;
struct rm_data_op {
unsigned int op_active:1;
+ unsigned int op_zcopy:1;
unsigned int op_nents;
unsigned int op_count;
unsigned int op_dmasg;
--
2.54.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH net] net/rds: fix zerocopy page ownership on partial copy failure
2026-05-10 21:20 [PATCH net] net/rds: fix zerocopy page ownership on partial copy failure Spencer ??
@ 2026-05-12 0:17 ` Jakub Kicinski
0 siblings, 0 replies; 2+ messages in thread
From: Jakub Kicinski @ 2026-05-12 0:17 UTC (permalink / raw)
To: Spencer ??
Cc: Allison Henderson, netdev@vger.kernel.org, David S. Miller,
Eric Dumazet, Paolo Abeni, Simon Horman,
linux-rdma@vger.kernel.org, rds-devel@oss.oracle.com,
linux-kernel@vger.kernel.org
On Sun, 10 May 2026 21:20:58 +0000 Spencer ?? wrote:
> From: Spencer ?? <spencer.phillips@live.com>
Your name is mangled in the From line, which git uses for the Author.
Please fix and repost.
--
pw-bot: cr
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-05-12 0:17 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-10 21:20 [PATCH net] net/rds: fix zerocopy page ownership on partial copy failure Spencer ??
2026-05-12 0:17 ` Jakub Kicinski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox