Commit 561c7df6 authored by Andy Grover's avatar Andy Grover Committed by David S. Miller

RDS: Do not call set_page_dirty() with irqs off

set_page_dirty() unconditionally re-enables interrupts, so
if we call it with irqs off, they will be on after the call,
and that's bad. This patch moves the call after we've re-enabled
interrupts in send_drop_to(), so it's safe.

Also, add BUG_ONs to let us know if we ever do call set_page_dirty
with interrupts off.
Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 450d06c0
...@@ -440,6 +440,7 @@ static void __rds_ib_teardown_mr(struct rds_ib_mr *ibmr) ...@@ -440,6 +440,7 @@ static void __rds_ib_teardown_mr(struct rds_ib_mr *ibmr)
/* FIXME we need a way to tell a r/w MR /* FIXME we need a way to tell a r/w MR
* from a r/o MR */ * from a r/o MR */
BUG_ON(in_interrupt());
set_page_dirty(page); set_page_dirty(page);
put_page(page); put_page(page);
} }
......
...@@ -438,8 +438,10 @@ void rds_rdma_free_op(struct rds_rdma_op *ro) ...@@ -438,8 +438,10 @@ void rds_rdma_free_op(struct rds_rdma_op *ro)
/* Mark page dirty if it was possibly modified, which /* Mark page dirty if it was possibly modified, which
* is the case for a RDMA_READ which copies from remote * is the case for a RDMA_READ which copies from remote
* to local memory */ * to local memory */
if (!ro->r_write) if (!ro->r_write) {
BUG_ON(in_interrupt());
set_page_dirty(page); set_page_dirty(page);
}
put_page(page); put_page(page);
} }
......
...@@ -507,12 +507,13 @@ EXPORT_SYMBOL_GPL(rds_send_get_message); ...@@ -507,12 +507,13 @@ EXPORT_SYMBOL_GPL(rds_send_get_message);
*/ */
void rds_send_remove_from_sock(struct list_head *messages, int status) void rds_send_remove_from_sock(struct list_head *messages, int status)
{ {
unsigned long flags = 0; /* silence gcc :P */ unsigned long flags;
struct rds_sock *rs = NULL; struct rds_sock *rs = NULL;
struct rds_message *rm; struct rds_message *rm;
local_irq_save(flags);
while (!list_empty(messages)) { while (!list_empty(messages)) {
int was_on_sock = 0;
rm = list_entry(messages->next, struct rds_message, rm = list_entry(messages->next, struct rds_message,
m_conn_item); m_conn_item);
list_del_init(&rm->m_conn_item); list_del_init(&rm->m_conn_item);
...@@ -527,7 +528,7 @@ void rds_send_remove_from_sock(struct list_head *messages, int status) ...@@ -527,7 +528,7 @@ void rds_send_remove_from_sock(struct list_head *messages, int status)
* while we're messing with it. It does not prevent the * while we're messing with it. It does not prevent the
* message from being removed from the socket, though. * message from being removed from the socket, though.
*/ */
spin_lock(&rm->m_rs_lock); spin_lock_irqsave(&rm->m_rs_lock, flags);
if (!test_bit(RDS_MSG_ON_SOCK, &rm->m_flags)) if (!test_bit(RDS_MSG_ON_SOCK, &rm->m_flags))
goto unlock_and_drop; goto unlock_and_drop;
...@@ -556,13 +557,15 @@ void rds_send_remove_from_sock(struct list_head *messages, int status) ...@@ -556,13 +557,15 @@ void rds_send_remove_from_sock(struct list_head *messages, int status)
notifier->n_status = status; notifier->n_status = status;
rm->m_rdma_op->r_notifier = NULL; rm->m_rdma_op->r_notifier = NULL;
} }
rds_message_put(rm); was_on_sock = 1;
rm->m_rs = NULL; rm->m_rs = NULL;
} }
spin_unlock(&rs->rs_lock); spin_unlock(&rs->rs_lock);
unlock_and_drop: unlock_and_drop:
spin_unlock(&rm->m_rs_lock); spin_unlock_irqrestore(&rm->m_rs_lock, flags);
rds_message_put(rm);
if (was_on_sock)
rds_message_put(rm); rds_message_put(rm);
} }
...@@ -570,7 +573,6 @@ void rds_send_remove_from_sock(struct list_head *messages, int status) ...@@ -570,7 +573,6 @@ void rds_send_remove_from_sock(struct list_head *messages, int status)
rds_wake_sk_sleep(rs); rds_wake_sk_sleep(rs);
sock_put(rds_rs_to_sk(rs)); sock_put(rds_rs_to_sk(rs));
} }
local_irq_restore(flags);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment