jbd2__journal_restart() has quite some code that is common with jbd2_journal_stop(). Factor this functionality into stop_this_handle() helper and use it from both functions. Note that this also drops t_handle_lock protection from jbd2__journal_restart() as jbd2_journal_stop() does the same thing without it.
Unified · Split
| @@ -512,12 +512,17 @@ handle_t *jbd2_journal_start(journal_t *journal, int nblocks) · 511 unmodified lines | |||
| 512 | } | 512 | } |
| 513 | EXPORT_SYMBOL(jbd2_journal_start); | 513 | EXPORT_SYMBOL(jbd2_journal_start); |
| 514 | 514 | ||
| 515 | void jbd2_journal_free_reserved(handle_t *handle) | 515 | static void __jbd2_journal_unreserve_handle(handle_t *handle) |
| 516 | { | 516 | { |
| 517 | journal_t *journal = handle->h_journal; | 517 | journal_t *journal = handle->h_journal; |
| 518 | 518 | ||
| 519 | WARN_ON(!handle->h_reserved); | 519 | WARN_ON(!handle->h_reserved); |
| 520 | sub_reserved_credits(journal, handle->h_buffer_credits); | 520 | sub_reserved_credits(journal, handle->h_buffer_credits); |
| 521 | } | ||
| 522 | |||
| 523 | void jbd2_journal_free_reserved(handle_t *handle) | ||
| 524 | { | ||
| 525 | __jbd2_journal_unreserve_handle(handle); | ||
| 521 | jbd2_free_handle(handle); | 526 | jbd2_free_handle(handle); |
| 522 | } | 527 | } |
| 523 | EXPORT_SYMBOL(jbd2_journal_free_reserved); | 528 | EXPORT_SYMBOL(jbd2_journal_free_reserved); |
| @@ -655,6 +660,28 @@ error_out: · 131 unmodified lines | |||
| 655 | return result; | 660 | return result; |
| 656 | } | 661 | } |
| 657 | 662 | ||
| 663 | static void stop_this_handle(handle_t *handle) | ||
| 664 | { | ||
| 665 | transaction_t *transaction = handle->h_transaction; | ||
| 666 | journal_t *journal = transaction->t_journal; | ||
| 667 | |||
| 668 | J_ASSERT(journal_current_handle() == handle); | ||
| 669 | J_ASSERT(atomic_read(&transaction->t_updates) > 0); | ||
| 670 | current->journal_info = NULL; | ||
| 671 | atomic_sub(handle->h_buffer_credits, | ||
| 672 | &transaction->t_outstanding_credits); | ||
| 673 | if (handle->h_rsv_handle) | ||
| 674 | __jbd2_journal_unreserve_handle(handle->h_rsv_handle); | ||
| 675 | if (atomic_dec_and_test(&transaction->t_updates)) | ||
| 676 | wake_up(&journal->j_wait_updates); | ||
| 677 | |||
| 678 | rwsem_release(&journal->j_trans_commit_map, 1, _THIS_IP_); | ||
| 679 | /* | ||
| 680 | * Scope of the GFP_NOFS context is over here and so we can restore the | ||
| 681 | * original alloc context. | ||
| 682 | */ | ||
| 683 | memalloc_nofs_restore(handle->saved_alloc_context); | ||
| 684 | } | ||
| 658 | 685 | ||
| 659 | /** | 686 | /** |
| 660 | * int jbd2_journal_restart() - restart a handle . | 687 | * int jbd2_journal_restart() - restart a handle . |
| @@ -677,52 +704,34 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask) · 16 unmodified lines | |||
| 677 | transaction_t *transaction = handle->h_transaction; | 704 | transaction_t *transaction = handle->h_transaction; |
| 678 | journal_t *journal; | 705 | journal_t *journal; |
| 679 | tid_t tid; | 706 | tid_t tid; |
| 680 | int need_to_start, ret; | 707 | int need_to_start; |
| 681 | 708 | ||
| 682 | /* If we've had an abort of any type, don't even think about | 709 | /* If we've had an abort of any type, don't even think about |
| 683 | * actually doing the restart! */ | 710 | * actually doing the restart! */ |
| 684 | if (is_handle_aborted(handle)) | 711 | if (is_handle_aborted(handle)) |
| 685 | return 0; | 712 | return 0; |
| 686 | journal = transaction->t_journal; | 713 | journal = transaction->t_journal; |
| 714 | tid = transaction->t_tid; | ||
| 687 | 715 | ||
| 688 | /* | 716 | /* |
| 689 | * First unlink the handle from its current transaction, and start the | 717 | * First unlink the handle from its current transaction, and start the |
| 690 | * commit on that. | 718 | * commit on that. |
| 691 | */ | 719 | */ |
| 692 | J_ASSERT(atomic_read(&transaction->t_updates) > 0); | 720 | jbd_debug(2, "restarting handle %p\n", handle); |
| 693 | J_ASSERT(journal_current_handle() == handle); | 721 | stop_this_handle(handle); |
| 694 | |||
| 695 | read_lock(&journal->j_state_lock); | ||
| 696 | spin_lock(&transaction->t_handle_lock); | ||
| 697 | atomic_sub(handle->h_buffer_credits, | ||
| 698 | &transaction->t_outstanding_credits); | ||
| 699 | if (handle->h_rsv_handle) { | ||
| 700 | sub_reserved_credits(journal, | ||
| 701 | handle->h_rsv_handle->h_buffer_credits); | ||
| 702 | } | ||
| 703 | if (atomic_dec_and_test(&transaction->t_updates)) | ||
| 704 | wake_up(&journal->j_wait_updates); | ||
| 705 | tid = transaction->t_tid; | ||
| 706 | spin_unlock(&transaction->t_handle_lock); | ||
| 707 | handle->h_transaction = NULL; | 722 | handle->h_transaction = NULL; |
| 708 | current->journal_info = NULL; | ||
| 709 | 723 | ||
| 710 | jbd_debug(2, "restarting handle %p\n", handle); | 724 | /* |
| 725 | * TODO: If we use READ_ONCE / WRITE_ONCE for j_commit_request we can | ||
| 726 | * get rid of pointless j_state_lock traffic like this. | ||
| 727 | */ | ||
| 728 | read_lock(&journal->j_state_lock); | ||
| 711 | need_to_start = !tid_geq(journal->j_commit_request, tid); | 729 | need_to_start = !tid_geq(journal->j_commit_request, tid); |
| 712 | read_unlock(&journal->j_state_lock); | 730 | read_unlock(&journal->j_state_lock); |
| 713 | if (need_to_start) | 731 | if (need_to_start) |
| 714 | jbd2_log_start_commit(journal, tid); | 732 | jbd2_log_start_commit(journal, tid); |
| 715 | |||
| 716 | rwsem_release(&journal->j_trans_commit_map, 1, _THIS_IP_); | ||
| 717 | handle->h_buffer_credits = nblocks; | 733 | handle->h_buffer_credits = nblocks; |
| 718 | /* | 734 | return start_this_handle(journal, handle, gfp_mask); |
| 719 | * Restore the original nofs context because the journal restart | ||
| 720 | * is basically the same thing as journal stop and start. | ||
| 721 | * start_this_handle will start a new nofs context. | ||
| 722 | */ | ||
| 723 | memalloc_nofs_restore(handle->saved_alloc_context); | ||
| 724 | ret = start_this_handle(journal, handle, gfp_mask); | ||
| 725 | return ret; | ||
| 726 | } | 735 | } |
| 727 | EXPORT_SYMBOL(jbd2__journal_restart); | 736 | EXPORT_SYMBOL(jbd2__journal_restart); |
| 728 | 737 | ||
| @@ -1718,16 +1727,12 @@ int jbd2_journal_stop(handle_t *handle) · 989 unmodified lines | |||
| 1718 | * Handle is already detached from the transaction so there is | 1727 | * Handle is already detached from the transaction so there is |
| 1719 | * nothing to do other than free the handle. | 1728 | * nothing to do other than free the handle. |
| 1720 | */ | 1729 | */ |
| 1721 | if (handle->h_rsv_handle) | 1730 | memalloc_nofs_restore(handle->saved_alloc_context); |
| 1722 | jbd2_free_handle(handle->h_rsv_handle); | ||
| 1723 | goto free_and_exit; | 1731 | goto free_and_exit; |
| 1724 | } | 1732 | } |
| 1725 | journal = transaction->t_journal; | 1733 | journal = transaction->t_journal; |
| 1726 | tid = transaction->t_tid; | 1734 | tid = transaction->t_tid; |
| 1727 | 1735 | ||
| 1728 | J_ASSERT(journal_current_handle() == handle); | ||
| 1729 | J_ASSERT(atomic_read(&transaction->t_updates) > 0); | ||
| 1730 | |||
| 1731 | if (is_handle_aborted(handle)) | 1736 | if (is_handle_aborted(handle)) |
| 1732 | err = -EIO; | 1737 | err = -EIO; |
| 1733 | 1738 | ||
| @@ -1797,9 +1802,6 @@ int jbd2_journal_stop(handle_t *handle) · 63 unmodified lines | |||
| 1797 | 1802 | ||
| 1798 | if (handle->h_sync) | 1803 | if (handle->h_sync) |
| 1799 | transaction->t_synchronous_commit = 1; | 1804 | transaction->t_synchronous_commit = 1; |
| 1800 | current->journal_info = NULL; | ||
| 1801 | atomic_sub(handle->h_buffer_credits, | ||
| 1802 | &transaction->t_outstanding_credits); | ||
| 1803 | 1805 | ||
| 1804 | /* | 1806 | /* |
| 1805 | * If the handle is marked SYNC, we need to set another commit | 1807 | * If the handle is marked SYNC, we need to set another commit |
| @@ -1826,27 +1828,19 @@ int jbd2_journal_stop(handle_t *handle) · 20 unmodified lines | |||
| 1826 | } | 1828 | } |
| 1827 | 1829 | ||
| 1828 | /* | 1830 | /* |
| 1829 | * Once we drop t_updates, if it goes to zero the transaction | 1831 | * Once stop_this_handle() drops t_updates, the transaction could start |
| 1830 | * could start committing on us and eventually disappear. So | 1832 | * committing on us and eventually disappear. So we must not |
| 1831 | * once we do this, we must not dereference transaction | 1833 | * dereference transaction pointer again after calling |
| 1832 | * pointer again. | 1834 | * stop_this_handle(). |
| 1833 | */ | 1835 | */ |
| 1834 | if (atomic_dec_and_test(&transaction->t_updates)) | 1836 | stop_this_handle(handle); |
| 1835 | wake_up(&journal->j_wait_updates); | ||
| 1836 | |||
| 1837 | rwsem_release(&journal->j_trans_commit_map, 1, _THIS_IP_); | ||
| 1838 | 1837 | ||
| 1839 | if (wait_for_commit) | 1838 | if (wait_for_commit) |
| 1840 | err = jbd2_log_wait_commit(journal, tid); | 1839 | err = jbd2_log_wait_commit(journal, tid); |
| 1841 | 1840 | ||
| 1842 | if (handle->h_rsv_handle) | ||
| 1843 | jbd2_journal_free_reserved(handle->h_rsv_handle); | ||
| 1844 | free_and_exit: | 1841 | free_and_exit: |
| 1845 | /* | 1842 | if (handle->h_rsv_handle) |
| 1846 | * Scope of the GFP_NOFS context is over here and so we can restore the | 1843 | jbd2_free_handle(handle->h_rsv_handle); |
| 1847 | * original alloc context. | ||
| 1848 | */ | ||
| 1849 | memalloc_nofs_restore(handle->saved_alloc_context); | ||
| 1850 | jbd2_free_handle(handle); | 1844 | jbd2_free_handle(handle); |
| 1851 | return err; | 1845 | return err; |
| 1852 | } | 1846 | } |