summaryrefslogtreecommitdiffstats
path: root/fs/jbd2
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-12-27 20:09:41 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-12-27 20:09:41 -0500
commitf6b1495fba0b66cfa05efa0ca2370513b79b45b6 (patch)
tree0718aab1784d4a65474404029e72ab288531462a /fs/jbd2
parentbc77789a491cdc6f47e5bbd1d04ddd283d64658b (diff)
parent18f2c4fcebf2582f96cbd5f2238f4f354a0e4847 (diff)
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 updates from Ted Ts'o: "All cleanups and bug fixes; most notably, fix some problems discovered in ext4's NFS support, and fix an ioctl (EXT4_IOC_GROUP_ADD) used by old versions of e2fsprogs which we accidentally broke a while back. Also fixed some error paths in ext4's quota and inline data support. Finally, improve tail latency in jbd2's commit code" * tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: check for shutdown and r/o file system in ext4_write_inode() ext4: force inode writes when nfsd calls commit_metadata() ext4: avoid declaring fs inconsistent due to invalid file handles ext4: include terminating u32 in size of xattr entries when expanding inodes ext4: compare old and new mode before setting update_mode flag ext4: fix EXT4_IOC_GROUP_ADD ioctl ext4: hard fail dax mount on unsupported devices jbd2: update locking documentation for transaction_t ext4: remove redundant condition check jbd2: clean up indentation issue, replace spaces with tab ext4: clean up indentation issues, remove extraneous tabs ext4: missing unlock/put_page() in ext4_try_to_write_inline_data() ext4: fix possible use after free in ext4_quota_enable jbd2: avoid long hold times of j_state_lock while committing a transaction ext4: add ext4_sb_bread() to disambiguate ENOMEM cases
Diffstat (limited to 'fs/jbd2')
-rw-r--r--fs/jbd2/commit.c3
-rw-r--r--fs/jbd2/transaction.c45
2 files changed, 42 insertions, 6 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 150cc030b4d7..2eb55c3361a8 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -439,6 +439,8 @@ void jbd2_journal_commit_transaction(journal_t *journal)
439 finish_wait(&journal->j_wait_updates, &wait); 439 finish_wait(&journal->j_wait_updates, &wait);
440 } 440 }
441 spin_unlock(&commit_transaction->t_handle_lock); 441 spin_unlock(&commit_transaction->t_handle_lock);
442 commit_transaction->t_state = T_SWITCH;
443 write_unlock(&journal->j_state_lock);
442 444
443 J_ASSERT (atomic_read(&commit_transaction->t_outstanding_credits) <= 445 J_ASSERT (atomic_read(&commit_transaction->t_outstanding_credits) <=
444 journal->j_max_transaction_buffers); 446 journal->j_max_transaction_buffers);
@@ -505,6 +507,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
505 atomic_sub(atomic_read(&journal->j_reserved_credits), 507 atomic_sub(atomic_read(&journal->j_reserved_credits),
506 &commit_transaction->t_outstanding_credits); 508 &commit_transaction->t_outstanding_credits);
507 509
510 write_lock(&journal->j_state_lock);
508 trace_jbd2_commit_flushing(journal, commit_transaction); 511 trace_jbd2_commit_flushing(journal, commit_transaction);
509 stats.run.rs_flushing = jiffies; 512 stats.run.rs_flushing = jiffies;
510 stats.run.rs_locked = jbd2_time_diff(stats.run.rs_locked, 513 stats.run.rs_locked = jbd2_time_diff(stats.run.rs_locked,
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index c0b66a7a795b..cc35537232f2 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -138,9 +138,9 @@ static inline void update_t_max_wait(transaction_t *transaction,
138} 138}
139 139
140/* 140/*
141 * Wait until running transaction passes T_LOCKED state. Also starts the commit 141 * Wait until running transaction passes to T_FLUSH state and new transaction
142 * if needed. The function expects running transaction to exist and releases 142 * can thus be started. Also starts the commit if needed. The function expects
143 * j_state_lock. 143 * running transaction to exist and releases j_state_lock.
144 */ 144 */
145static void wait_transaction_locked(journal_t *journal) 145static void wait_transaction_locked(journal_t *journal)
146 __releases(journal->j_state_lock) 146 __releases(journal->j_state_lock)
@@ -160,6 +160,32 @@ static void wait_transaction_locked(journal_t *journal)
160 finish_wait(&journal->j_wait_transaction_locked, &wait); 160 finish_wait(&journal->j_wait_transaction_locked, &wait);
161} 161}
162 162
163/*
164 * Wait until running transaction transitions from T_SWITCH to T_FLUSH
165 * state and new transaction can thus be started. The function releases
166 * j_state_lock.
167 */
168static void wait_transaction_switching(journal_t *journal)
169 __releases(journal->j_state_lock)
170{
171 DEFINE_WAIT(wait);
172
173 if (WARN_ON(!journal->j_running_transaction ||
174 journal->j_running_transaction->t_state != T_SWITCH))
175 return;
176 prepare_to_wait(&journal->j_wait_transaction_locked, &wait,
177 TASK_UNINTERRUPTIBLE);
178 read_unlock(&journal->j_state_lock);
179 /*
180 * We don't call jbd2_might_wait_for_commit() here as there's no
181 * waiting for outstanding handles happening anymore in T_SWITCH state
182 * and handling of reserved handles actually relies on that for
183 * correctness.
184 */
185 schedule();
186 finish_wait(&journal->j_wait_transaction_locked, &wait);
187}
188
163static void sub_reserved_credits(journal_t *journal, int blocks) 189static void sub_reserved_credits(journal_t *journal, int blocks)
164{ 190{
165 atomic_sub(blocks, &journal->j_reserved_credits); 191 atomic_sub(blocks, &journal->j_reserved_credits);
@@ -183,7 +209,8 @@ static int add_transaction_credits(journal_t *journal, int blocks,
183 * If the current transaction is locked down for commit, wait 209 * If the current transaction is locked down for commit, wait
184 * for the lock to be released. 210 * for the lock to be released.
185 */ 211 */
186 if (t->t_state == T_LOCKED) { 212 if (t->t_state != T_RUNNING) {
213 WARN_ON_ONCE(t->t_state >= T_FLUSH);
187 wait_transaction_locked(journal); 214 wait_transaction_locked(journal);
188 return 1; 215 return 1;
189 } 216 }
@@ -360,8 +387,14 @@ repeat:
360 /* 387 /*
361 * We have handle reserved so we are allowed to join T_LOCKED 388 * We have handle reserved so we are allowed to join T_LOCKED
362 * transaction and we don't have to check for transaction size 389 * transaction and we don't have to check for transaction size
363 * and journal space. 390 * and journal space. But we still have to wait while running
391 * transaction is being switched to a committing one as it
392 * won't wait for any handles anymore.
364 */ 393 */
394 if (transaction->t_state == T_SWITCH) {
395 wait_transaction_switching(journal);
396 goto repeat;
397 }
365 sub_reserved_credits(journal, blocks); 398 sub_reserved_credits(journal, blocks);
366 handle->h_reserved = 0; 399 handle->h_reserved = 0;
367 } 400 }
@@ -910,7 +943,7 @@ repeat:
910 * this is the first time this transaction is touching this buffer, 943 * this is the first time this transaction is touching this buffer,
911 * reset the modified flag 944 * reset the modified flag
912 */ 945 */
913 jh->b_modified = 0; 946 jh->b_modified = 0;
914 947
915 /* 948 /*
916 * If the buffer is not journaled right now, we need to make sure it 949 * If the buffer is not journaled right now, we need to make sure it