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 /net/rds | |
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>
Diffstat (limited to 'net/rds')
-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 | /* |