patch-2.4.20 linux-2.4.20/fs/jbd/commit.c
Next file: linux-2.4.20/fs/jbd/journal.c
Previous file: linux-2.4.20/fs/jbd/checkpoint.c
Back to the patch index
Back to the overall index
- Lines: 89
- Date:
Thu Nov 28 15:53:15 2002
- Orig file:
linux-2.4.19/fs/jbd/commit.c
- Orig date:
Mon Feb 25 11:38:08 2002
diff -urN linux-2.4.19/fs/jbd/commit.c linux-2.4.20/fs/jbd/commit.c
@@ -475,7 +475,7 @@
transaction's t_log_list queue, and metadata buffers are on
the t_iobuf_list queue.
- Wait for the transactions in reverse order. That way we are
+ Wait for the buffers in reverse order. That way we are
less likely to be woken up until all IOs have completed, and
so we incur less scheduling load.
*/
@@ -566,8 +566,10 @@
jbd_debug(3, "JBD: commit phase 6\n");
- if (is_journal_aborted(journal))
+ if (is_journal_aborted(journal)) {
+ unlock_journal(journal);
goto skip_commit;
+ }
/* Done it all: now write the commit record. We should have
* cleaned up our previous buffers by now, so if we are in abort
@@ -577,9 +579,10 @@
descriptor = journal_get_descriptor_buffer(journal);
if (!descriptor) {
__journal_abort_hard(journal);
+ unlock_journal(journal);
goto skip_commit;
}
-
+
/* AKPM: buglet - add `i' to tmp! */
for (i = 0; i < jh2bh(descriptor)->b_size; i += 512) {
journal_header_t *tmp =
@@ -600,14 +603,32 @@
put_bh(bh); /* One for getblk() */
journal_unlock_journal_head(descriptor);
}
- lock_journal(journal);
/* End of a transaction! Finally, we can do checkpoint
processing: any buffers committed as a result of this
transaction can be removed from any checkpoint list it was on
before. */
-skip_commit:
+skip_commit: /* The journal should be unlocked by now. */
+
+ /* Call any callbacks that had been registered for handles in this
+ * transaction. It is up to the callback to free any allocated
+ * memory.
+ */
+ if (!list_empty(&commit_transaction->t_jcb)) {
+ struct list_head *p, *n;
+ int error = is_journal_aborted(journal);
+
+ list_for_each_safe(p, n, &commit_transaction->t_jcb) {
+ struct journal_callback *jcb;
+
+ jcb = list_entry(p, struct journal_callback, jcb_list);
+ list_del(p);
+ jcb->jcb_func(jcb, error);
+ }
+ }
+
+ lock_journal(journal);
jbd_debug(3, "JBD: commit phase 7\n");
@@ -663,6 +684,20 @@
* there's no point in keeping a checkpoint record for
* it. */
bh = jh2bh(jh);
+
+ /* A buffer which has been freed while still being
+ * journaled by a previous transaction may end up still
+ * being dirty here, but we want to avoid writing back
+ * that buffer in the future now that the last use has
+ * been committed. That's not only a performance gain,
+ * it also stops aliasing problems if the buffer is left
+ * behind for writeback and gets reallocated for another
+ * use in a different page. */
+ if (__buffer_state(bh, Freed)) {
+ clear_bit(BH_Freed, &bh->b_state);
+ clear_bit(BH_JBDDirty, &bh->b_state);
+ }
+
if (buffer_jdirty(bh)) {
JBUFFER_TRACE(jh, "add to new checkpointing trans");
__journal_insert_checkpoint(jh, commit_transaction);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)