VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / fs / jbd / journal.c
index 3c95df4..1cf23ff 100644 (file)
@@ -73,6 +73,7 @@ EXPORT_SYMBOL(journal_ack_err);
 EXPORT_SYMBOL(journal_clear_err);
 EXPORT_SYMBOL(log_wait_commit);
 EXPORT_SYMBOL(journal_start_commit);
+EXPORT_SYMBOL(journal_force_commit_nested);
 EXPORT_SYMBOL(journal_wipe);
 EXPORT_SYMBOL(journal_blocks_per_page);
 EXPORT_SYMBOL(journal_invalidatepage);
@@ -464,6 +465,39 @@ int log_start_commit(journal_t *journal, tid_t tid)
        return ret;
 }
 
+/*
+ * Force and wait upon a commit if the calling process is not within
+ * transaction.  This is used for forcing out undo-protected data which contains
+ * bitmaps, when the fs is running out of space.
+ *
+ * We can only force the running transaction if we don't have an active handle;
+ * otherwise, we will deadlock.
+ *
+ * Returns true if a transaction was started.
+ */
+int journal_force_commit_nested(journal_t *journal)
+{
+       transaction_t *transaction = NULL;
+       tid_t tid;
+
+       spin_lock(&journal->j_state_lock);
+       if (journal->j_running_transaction && !current->journal_info) {
+               transaction = journal->j_running_transaction;
+               __log_start_commit(journal, transaction->t_tid);
+       } else if (journal->j_committing_transaction)
+               transaction = journal->j_committing_transaction;
+
+       if (!transaction) {
+               spin_unlock(&journal->j_state_lock);
+               return 0;       /* Nothing to retry */
+       }
+
+       tid = transaction->t_tid;
+       spin_unlock(&journal->j_state_lock);
+       log_wait_commit(journal, tid);
+       return 1;
+}
+
 /*
  * Start a commit of the current running transaction (if any).  Returns true
  * if a transaction was started, and fills its tid in at *ptid
@@ -585,9 +619,13 @@ int journal_bmap(journal_t *journal, unsigned long blocknr,
  * We play buffer_head aliasing tricks to write data/metadata blocks to
  * the journal without copying their contents, but for journal
  * descriptor blocks we do need to generate bona fide buffers.
+ *
+ * After the caller of journal_get_descriptor_buffer() has finished modifying
+ * the buffer's contents they really should run flush_dcache_page(bh->b_page).
+ * But we don't bother doing that, so there will be coherency problems with
+ * mmaps of blockdevs which hold live JBD-controlled filesystems.
  */
-
-struct journal_head * journal_get_descriptor_buffer(journal_t *journal)
+struct journal_head *journal_get_descriptor_buffer(journal_t *journal)
 {
        struct buffer_head *bh;
        unsigned long blocknr;
@@ -599,8 +637,10 @@ struct journal_head * journal_get_descriptor_buffer(journal_t *journal)
                return NULL;
 
        bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
+       lock_buffer(bh);
        memset(bh->b_data, 0, journal->j_blocksize);
-       bh->b_state |= (1 << BH_Dirty);
+       set_buffer_uptodate(bh);
+       unlock_buffer(bh);
        BUFFER_TRACE(bh, "return this buffer");
        return journal_add_journal_head(bh);
 }
@@ -1577,7 +1617,7 @@ static void journal_destroy_journal_head_cache(void)
 {
        J_ASSERT(journal_head_cache != NULL);
        kmem_cache_destroy(journal_head_cache);
-       journal_head_cache = 0;
+       journal_head_cache = NULL;
 }
 
 /*