summaryrefslogtreecommitdiff
path: root/net/rds/message.c
diff options
context:
space:
mode:
authorSowmini Varadhan <sowmini.varadhan@oracle.com>2018-02-15 10:49:33 -0800
committerDavid S. Miller <davem@davemloft.net>2018-02-16 16:04:16 -0500
commitea8994cb0118993da179af836cc72a583d75dc4b (patch)
tree4e7f99f47475dfc9343cdb46066e1f515f2bfc0f /net/rds/message.c
parent6f89dbce8e1134458de8a8e376acaaca4eee602e (diff)
rds: hold a sock ref from rds_message to the rds_sock
The existing model holds a reference from the rds_sock to the rds_message, but the rds_message does not itself hold a sock_put() on the rds_sock. Instead the m_rs field in the rds_message is assigned when the message is queued on the sock, and nulled when the message is dequeued from the sock. We want to be able to notify userspace when the rds_message is actually freed (from rds_message_purge(), after the refcounts to the rds_message go to 0). At the time that rds_message_purge() is called, the message is no longer on the rds_sock retransmit queue. Thus the explicit reference for the m_rs is needed to send a notification that will signal to userspace that it is now safe to free/reuse any pages that may have been pinned down for zerocopy. This patch manages the m_rs assignment in the rds_message with the necessary refcount book-keeping. Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com> Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/rds/message.c')
-rw-r--r--net/rds/message.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/net/rds/message.c b/net/rds/message.c
index 4318cc9b78f7..ef3daafa3d79 100644
--- a/net/rds/message.c
+++ b/net/rds/message.c
@@ -58,7 +58,7 @@ EXPORT_SYMBOL_GPL(rds_message_addref);
*/
static void rds_message_purge(struct rds_message *rm)
{
- unsigned long i;
+ unsigned long i, flags;
if (unlikely(test_bit(RDS_MSG_PAGEVEC, &rm->m_flags)))
return;
@@ -69,6 +69,12 @@ static void rds_message_purge(struct rds_message *rm)
__free_page(sg_page(&rm->data.op_sg[i]));
}
rm->data.op_nents = 0;
+ spin_lock_irqsave(&rm->m_rs_lock, flags);
+ if (rm->m_rs) {
+ sock_put(rds_rs_to_sk(rm->m_rs));
+ rm->m_rs = NULL;
+ }
+ spin_unlock_irqrestore(&rm->m_rs_lock, flags);
if (rm->rdma.op_active)
rds_rdma_free_op(&rm->rdma);