diff options
| author | Andy Grover <andy.grover@oracle.com> | 2010-03-11 08:50:06 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2010-03-17 00:17:01 -0400 |
| commit | 561c7df63e259203515509a7ad075382a42bff0c (patch) | |
| tree | 80d3d382ba155d4bced37b716dcac0e31062f2c5 | |
| parent | 450d06c0208ad195ccd74a7edd11321e316791ad (diff) | |
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: Andy Grover <andy.grover@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | net/rds/ib_rdma.c | 1 | ||||
| -rw-r--r-- | net/rds/rdma.c | 4 | ||||
| -rw-r--r-- | net/rds/send.c | 14 |
3 files changed, 12 insertions, 7 deletions
diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c index 65e668defe42..cfb1d904ed00 100644 --- a/net/rds/ib_rdma.c +++ b/net/rds/ib_rdma.c | |||
| @@ -440,6 +440,7 @@ static void __rds_ib_teardown_mr(struct rds_ib_mr *ibmr) | |||
| 440 | 440 | ||
| 441 | /* FIXME we need a way to tell a r/w MR | 441 | /* FIXME we need a way to tell a r/w MR |
| 442 | * from a r/o MR */ | 442 | * from a r/o MR */ |
| 443 | BUG_ON(in_interrupt()); | ||
| 443 | set_page_dirty(page); | 444 | set_page_dirty(page); |
| 444 | put_page(page); | 445 | put_page(page); |
| 445 | } | 446 | } |
diff --git a/net/rds/rdma.c b/net/rds/rdma.c index 4c64daa1f5d5..61b359d9dffd 100644 --- a/net/rds/rdma.c +++ b/net/rds/rdma.c | |||
| @@ -438,8 +438,10 @@ void rds_rdma_free_op(struct rds_rdma_op *ro) | |||
| 438 | /* Mark page dirty if it was possibly modified, which | 438 | /* Mark page dirty if it was possibly modified, which |
| 439 | * is the case for a RDMA_READ which copies from remote | 439 | * is the case for a RDMA_READ which copies from remote |
| 440 | * to local memory */ | 440 | * to local memory */ |
| 441 | if (!ro->r_write) | 441 | if (!ro->r_write) { |
| 442 | BUG_ON(in_interrupt()); | ||
| 442 | set_page_dirty(page); | 443 | set_page_dirty(page); |
| 444 | } | ||
| 443 | put_page(page); | 445 | put_page(page); |
| 444 | } | 446 | } |
| 445 | 447 | ||
diff --git a/net/rds/send.c b/net/rds/send.c index 51e2def50b12..4629a0b63bbd 100644 --- a/net/rds/send.c +++ b/net/rds/send.c | |||
| @@ -507,12 +507,13 @@ EXPORT_SYMBOL_GPL(rds_send_get_message); | |||
| 507 | */ | 507 | */ |
| 508 | void rds_send_remove_from_sock(struct list_head *messages, int status) | 508 | void rds_send_remove_from_sock(struct list_head *messages, int status) |
| 509 | { | 509 | { |
| 510 | unsigned long flags = 0; /* silence gcc :P */ | 510 | unsigned long flags; |
| 511 | struct rds_sock *rs = NULL; | 511 | struct rds_sock *rs = NULL; |
| 512 | struct rds_message *rm; | 512 | struct rds_message *rm; |
| 513 | 513 | ||
| 514 | local_irq_save(flags); | ||
| 515 | while (!list_empty(messages)) { | 514 | while (!list_empty(messages)) { |
| 515 | int was_on_sock = 0; | ||
| 516 | |||
| 516 | rm = list_entry(messages->next, struct rds_message, | 517 | rm = list_entry(messages->next, struct rds_message, |
| 517 | m_conn_item); | 518 | m_conn_item); |
| 518 | list_del_init(&rm->m_conn_item); | 519 | list_del_init(&rm->m_conn_item); |
| @@ -527,7 +528,7 @@ void rds_send_remove_from_sock(struct list_head *messages, int status) | |||
| 527 | * while we're messing with it. It does not prevent the | 528 | * while we're messing with it. It does not prevent the |
| 528 | * message from being removed from the socket, though. | 529 | * message from being removed from the socket, though. |
| 529 | */ | 530 | */ |
| 530 | spin_lock(&rm->m_rs_lock); | 531 | spin_lock_irqsave(&rm->m_rs_lock, flags); |
| 531 | if (!test_bit(RDS_MSG_ON_SOCK, &rm->m_flags)) | 532 | if (!test_bit(RDS_MSG_ON_SOCK, &rm->m_flags)) |
| 532 | goto unlock_and_drop; | 533 | goto unlock_and_drop; |
| 533 | 534 | ||
| @@ -556,21 +557,22 @@ void rds_send_remove_from_sock(struct list_head *messages, int status) | |||
| 556 | notifier->n_status = status; | 557 | notifier->n_status = status; |
| 557 | rm->m_rdma_op->r_notifier = NULL; | 558 | rm->m_rdma_op->r_notifier = NULL; |
| 558 | } | 559 | } |
| 559 | rds_message_put(rm); | 560 | was_on_sock = 1; |
| 560 | rm->m_rs = NULL; | 561 | rm->m_rs = NULL; |
| 561 | } | 562 | } |
| 562 | spin_unlock(&rs->rs_lock); | 563 | spin_unlock(&rs->rs_lock); |
| 563 | 564 | ||
| 564 | unlock_and_drop: | 565 | unlock_and_drop: |
| 565 | spin_unlock(&rm->m_rs_lock); | 566 | spin_unlock_irqrestore(&rm->m_rs_lock, flags); |
| 566 | rds_message_put(rm); | 567 | rds_message_put(rm); |
| 568 | if (was_on_sock) | ||
| 569 | rds_message_put(rm); | ||
| 567 | } | 570 | } |
| 568 | 571 | ||
| 569 | if (rs) { | 572 | if (rs) { |
| 570 | rds_wake_sk_sleep(rs); | 573 | rds_wake_sk_sleep(rs); |
| 571 | sock_put(rds_rs_to_sk(rs)); | 574 | sock_put(rds_rs_to_sk(rs)); |
| 572 | } | 575 | } |
| 573 | local_irq_restore(flags); | ||
| 574 | } | 576 | } |
| 575 | 577 | ||
| 576 | /* | 578 | /* |
