add patch fix-fsync-error-handling-after-filesystem-abort
[ext4-patch-queue.git] / optimize-jbd2_journal_force_commit
blobd8013409f82af6d03932daaaa99e4ea5f4fd624e
1 jbd2: optimize jbd2_journal_force_commit
3 From: Dmitry Monakhov <dmonakhov@openvz.org>
5 Current implementation of jbd2_journal_force_commit() is suboptimal because
6 result in empty and useless commits. But callers just want to force and wait
7 any unfinished commits. We already have jbd2_journal_force_commit_nested()
8 which does exactly what we want, except we are guaranteed that we do not hold
9 journal transaction open.
11 Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
12 Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
13 ---
14  fs/jbd2/journal.c     | 62 ++++++++++++++++++++++++++++++++++++++++++++++++--------------
15  fs/jbd2/transaction.c | 23 -----------------------
16  include/linux/jbd2.h  |  2 +-
17  3 files changed, 49 insertions(+), 38 deletions(-)
19 diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
20 index 70990d6..0e6c13b 100644
21 --- a/fs/jbd2/journal.c
22 +++ b/fs/jbd2/journal.c
23 @@ -529,20 +529,17 @@ int jbd2_log_start_commit(journal_t *journal, tid_t tid)
24  }
26  /*
27 - * Force and wait upon a commit if the calling process is not within
28 - * transaction.  This is used for forcing out undo-protected data which contains
29 - * bitmaps, when the fs is running out of space.
30 - *
31 - * We can only force the running transaction if we don't have an active handle;
32 - * otherwise, we will deadlock.
33 - *
34 - * Returns true if a transaction was started.
35 + * Force and wait any uncommitted transactions.  We can only force the running
36 + * transaction if we don't have an active handle, otherwise, we will deadlock.
37 + * Returns: <0 in case of error,
38 + *           0 if nothing to commit,
39 + *           1 if transaction was successfully committed.
40   */
41 -int jbd2_journal_force_commit_nested(journal_t *journal)
42 +static int __jbd2_journal_force_commit(journal_t *journal)
43  {
44         transaction_t *transaction = NULL;
45         tid_t tid;
46 -       int need_to_start = 0;
47 +       int need_to_start = 0, ret = 0;
49         read_lock(&journal->j_state_lock);
50         if (journal->j_running_transaction && !current->journal_info) {
51 @@ -553,16 +550,53 @@ int jbd2_journal_force_commit_nested(journal_t *journal)
52                 transaction = journal->j_committing_transaction;
54         if (!transaction) {
55 +               /* Nothing to commit */
56                 read_unlock(&journal->j_state_lock);
57 -               return 0;       /* Nothing to retry */
58 +               return 0;
59         }
61         tid = transaction->t_tid;
62         read_unlock(&journal->j_state_lock);
63         if (need_to_start)
64                 jbd2_log_start_commit(journal, tid);
65 -       jbd2_log_wait_commit(journal, tid);
66 -       return 1;
67 +       ret = jbd2_log_wait_commit(journal, tid);
68 +       if (!ret)
69 +               ret = 1;
71 +       return ret;
74 +/**
75 + * Force and wait upon a commit if the calling process is not within
76 + * transaction.  This is used for forcing out undo-protected data which contains
77 + * bitmaps, when the fs is running out of space.
78 + *
79 + * @journal: journal to force
80 + * Returns true if progress was made.
81 + */
82 +int jbd2_journal_force_commit_nested(journal_t *journal)
84 +       int ret;
86 +       ret = __jbd2_journal_force_commit(journal);
87 +       return ret > 0;
90 +/**
91 + * int journal_force_commit() - force any uncommitted transactions
92 + * @journal: journal to force
93 + *
94 + * Caller want unconditional commit. We can only force the running transaction
95 + * if we don't have an active handle, otherwise, we will deadlock.
96 + */
97 +int jbd2_journal_force_commit(journal_t *journal)
99 +       int ret;
101 +       J_ASSERT(!current->journal_info);
102 +       ret = __jbd2_journal_force_commit(journal);
103 +       if (ret > 0)
104 +               ret = 0;
105 +       return ret;
108  /*
109 diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
110 index f33342a..dd422e6 100644
111 --- a/fs/jbd2/transaction.c
112 +++ b/fs/jbd2/transaction.c
113 @@ -1661,29 +1661,6 @@ int jbd2_journal_stop(handle_t *handle)
114         return err;
117 -/**
118 - * int jbd2_journal_force_commit() - force any uncommitted transactions
119 - * @journal: journal to force
120 - *
121 - * For synchronous operations: force any uncommitted transactions
122 - * to disk.  May seem kludgy, but it reuses all the handle batching
123 - * code in a very simple manner.
124 - */
125 -int jbd2_journal_force_commit(journal_t *journal)
127 -       handle_t *handle;
128 -       int ret;
130 -       handle = jbd2_journal_start(journal, 1);
131 -       if (IS_ERR(handle)) {
132 -               ret = PTR_ERR(handle);
133 -       } else {
134 -               handle->h_sync = 1;
135 -               ret = jbd2_journal_stop(handle);
136 -       }
137 -       return ret;
140  /*
141   *
142   * List management code snippets: various functions for manipulating the
143 diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
144 index fb91c8d..c3645b9 100644
145 --- a/include/linux/jbd2.h
146 +++ b/include/linux/jbd2.h
147 @@ -1160,6 +1160,7 @@ extern void          jbd2_journal_ack_err    (journal_t *);
148  extern int        jbd2_journal_clear_err  (journal_t *);
149  extern int        jbd2_journal_bmap(journal_t *, unsigned long, unsigned long long *);
150  extern int        jbd2_journal_force_commit(journal_t *);
151 +extern int        jbd2_journal_force_commit_nested(journal_t *);
152  extern int        jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *inode);
153  extern int        jbd2_journal_begin_ordered_truncate(journal_t *journal,
154                                 struct jbd2_inode *inode, loff_t new_size);
155 @@ -1235,7 +1236,6 @@ extern void       jbd2_clear_buffer_revoked_flags(journal_t *journal);
156  int jbd2_log_start_commit(journal_t *journal, tid_t tid);
157  int __jbd2_log_start_commit(journal_t *journal, tid_t tid);
158  int jbd2_journal_start_commit(journal_t *journal, tid_t *tid);
159 -int jbd2_journal_force_commit_nested(journal_t *journal);
160  int jbd2_log_wait_commit(journal_t *journal, tid_t tid);
161  int jbd2_complete_transaction(journal_t *journal, tid_t tid);
162  int jbd2_log_do_checkpoint(journal_t *journal);