summaryrefslogtreecommitdiffstats
path: root/fs/jbd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jbd')
-rw-r--r--fs/jbd/checkpoint.c2
-rw-r--r--fs/jbd/commit.c38
-rw-r--r--fs/jbd/journal.c38
-rw-r--r--fs/jbd/revoke.c5
-rw-r--r--fs/jbd/transaction.c39
5 files changed, 68 insertions, 54 deletions
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c
index 5a97e34..014a51f 100644
--- a/fs/jbd/checkpoint.c
+++ b/fs/jbd/checkpoint.c
@@ -204,7 +204,7 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
int i;
spin_unlock(&journal->j_list_lock);
- ll_rw_block(WRITE, *batch_count, bhs);
+ ll_rw_block(SWRITE, *batch_count, bhs);
spin_lock(&journal->j_list_lock);
for (i = 0; i < *batch_count; i++) {
struct buffer_head *bh = bhs[i];
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index dac720c..2a3e310 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -358,7 +358,7 @@ write_out_data:
jbd_debug(2, "submit %d writes\n",
bufs);
spin_unlock(&journal->j_list_lock);
- ll_rw_block(WRITE, bufs, wbuf);
+ ll_rw_block(SWRITE, bufs, wbuf);
journal_brelse_array(wbuf, bufs);
bufs = 0;
goto write_out_data;
@@ -381,7 +381,7 @@ write_out_data:
if (bufs) {
spin_unlock(&journal->j_list_lock);
- ll_rw_block(WRITE, bufs, wbuf);
+ ll_rw_block(SWRITE, bufs, wbuf);
journal_brelse_array(wbuf, bufs);
spin_lock(&journal->j_list_lock);
}
@@ -720,11 +720,17 @@ wait_for_iobuf:
J_ASSERT(commit_transaction->t_log_list == NULL);
restart_loop:
+ /*
+ * As there are other places (journal_unmap_buffer()) adding buffers
+ * to this list we have to be careful and hold the j_list_lock.
+ */
+ spin_lock(&journal->j_list_lock);
while (commit_transaction->t_forget) {
transaction_t *cp_transaction;
struct buffer_head *bh;
jh = commit_transaction->t_forget;
+ spin_unlock(&journal->j_list_lock);
bh = jh2bh(jh);
jbd_lock_bh_state(bh);
J_ASSERT_JH(jh, jh->b_transaction == commit_transaction ||
@@ -792,9 +798,25 @@ restart_loop:
journal_remove_journal_head(bh); /* needs a brelse */
release_buffer_page(bh);
}
+ cond_resched_lock(&journal->j_list_lock);
+ }
+ spin_unlock(&journal->j_list_lock);
+ /*
+ * This is a bit sleazy. We borrow j_list_lock to protect
+ * journal->j_committing_transaction in __journal_remove_checkpoint.
+ * Really, __journal_remove_checkpoint should be using j_state_lock but
+ * it's a bit hassle to hold that across __journal_remove_checkpoint
+ */
+ spin_lock(&journal->j_state_lock);
+ spin_lock(&journal->j_list_lock);
+ /*
+ * Now recheck if some buffers did not get attached to the transaction
+ * while the lock was dropped...
+ */
+ if (commit_transaction->t_forget) {
spin_unlock(&journal->j_list_lock);
- if (cond_resched())
- goto restart_loop;
+ spin_unlock(&journal->j_state_lock);
+ goto restart_loop;
}
/* Done with this transaction! */
@@ -803,14 +825,6 @@ restart_loop:
J_ASSERT(commit_transaction->t_state == T_COMMIT);
- /*
- * This is a bit sleazy. We borrow j_list_lock to protect
- * journal->j_committing_transaction in __journal_remove_checkpoint.
- * Really, __jornal_remove_checkpoint should be using j_state_lock but
- * it's a bit hassle to hold that across __journal_remove_checkpoint
- */
- spin_lock(&journal->j_state_lock);
- spin_lock(&journal->j_list_lock);
commit_transaction->t_state = T_FINISHED;
J_ASSERT(commit_transaction == journal->j_committing_transaction);
journal->j_commit_sequence = commit_transaction->t_tid;
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 5e7b439..7ae2c4f 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -65,7 +65,6 @@ EXPORT_SYMBOL(journal_set_features);
EXPORT_SYMBOL(journal_create);
EXPORT_SYMBOL(journal_load);
EXPORT_SYMBOL(journal_destroy);
-EXPORT_SYMBOL(journal_recover);
EXPORT_SYMBOL(journal_update_superblock);
EXPORT_SYMBOL(journal_abort);
EXPORT_SYMBOL(journal_errno);
@@ -81,6 +80,7 @@ EXPORT_SYMBOL(journal_try_to_free_buffers);
EXPORT_SYMBOL(journal_force_commit);
static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
+static void __journal_abort_soft (journal_t *journal, int errno);
/*
* Helper function used to manage commit timeouts
@@ -93,16 +93,6 @@ static void commit_timeout(unsigned long __data)
wake_up_process(p);
}
-/* Static check for data structure consistency. There's no code
- * invoked --- we'll just get a linker failure if things aren't right.
- */
-void __journal_internal_check(void)
-{
- extern void journal_bad_superblock_size(void);
- if (sizeof(struct journal_superblock_s) != 1024)
- journal_bad_superblock_size();
-}
-
/*
* kjournald: The main thread function used to manage a logging device
* journal.
@@ -119,16 +109,12 @@ void __journal_internal_check(void)
* known as checkpointing, and this thread is responsible for that job.
*/
-journal_t *current_journal; // AKPM: debug
-
-int kjournald(void *arg)
+static int kjournald(void *arg)
{
journal_t *journal = (journal_t *) arg;
transaction_t *transaction;
struct timer_list timer;
- current_journal = journal;
-
daemonize("kjournald");
/* Set up an interval timer which can be used to trigger a
@@ -193,6 +179,8 @@ loop:
if (transaction && time_after_eq(jiffies,
transaction->t_expires))
should_sleep = 0;
+ if (journal->j_flags & JFS_UNMOUNT)
+ should_sleep = 0;
if (should_sleep) {
spin_unlock(&journal->j_state_lock);
schedule();
@@ -969,7 +957,7 @@ void journal_update_superblock(journal_t *journal, int wait)
if (wait)
sync_dirty_buffer(bh);
else
- ll_rw_block(WRITE, 1, &bh);
+ ll_rw_block(SWRITE, 1, &bh);
out:
/* If we have just flushed the log (by marking s_start==0), then
@@ -1439,7 +1427,7 @@ int journal_wipe(journal_t *journal, int write)
* device this journal is present.
*/
-const char *journal_dev_name(journal_t *journal, char *buffer)
+static const char *journal_dev_name(journal_t *journal, char *buffer)
{
struct block_device *bdev;
@@ -1485,7 +1473,7 @@ void __journal_abort_hard(journal_t *journal)
/* Soft abort: record the abort error status in the journal superblock,
* but don't do any other IO. */
-void __journal_abort_soft (journal_t *journal, int errno)
+static void __journal_abort_soft (journal_t *journal, int errno)
{
if (journal->j_flags & JFS_ABORT)
return;
@@ -1880,7 +1868,7 @@ EXPORT_SYMBOL(journal_enable_debug);
static struct proc_dir_entry *proc_jbd_debug;
-int read_jbd_debug(char *page, char **start, off_t off,
+static int read_jbd_debug(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int ret;
@@ -1890,7 +1878,7 @@ int read_jbd_debug(char *page, char **start, off_t off,
return ret;
}
-int write_jbd_debug(struct file *file, const char __user *buffer,
+static int write_jbd_debug(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char buf[32];
@@ -1979,6 +1967,14 @@ static int __init journal_init(void)
{
int ret;
+/* Static check for data structure consistency. There's no code
+ * invoked --- we'll just get a linker failure if things aren't right.
+ */
+ extern void journal_bad_superblock_size(void);
+ if (sizeof(struct journal_superblock_s) != 1024)
+ journal_bad_superblock_size();
+
+
ret = journal_init_caches();
if (ret != 0)
journal_destroy_caches();
diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c
index d327a59..a561441 100644
--- a/fs/jbd/revoke.c
+++ b/fs/jbd/revoke.c
@@ -116,7 +116,8 @@ static inline int hash(journal_t *journal, unsigned long block)
(block << (hash_shift - 12))) & (table->hash_size - 1);
}
-int insert_revoke_hash(journal_t *journal, unsigned long blocknr, tid_t seq)
+static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
+ tid_t seq)
{
struct list_head *hash_list;
struct jbd_revoke_record_s *record;
@@ -613,7 +614,7 @@ static void flush_descriptor(journal_t *journal,
set_buffer_jwrite(bh);
BUFFER_TRACE(bh, "write");
set_buffer_dirty(bh);
- ll_rw_block(WRITE, 1, &bh);
+ ll_rw_block(SWRITE, 1, &bh);
}
#endif
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 77b7662..c6ec66f 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -490,23 +490,21 @@ void journal_unlock_updates (journal_t *journal)
*/
static void jbd_unexpected_dirty_buffer(struct journal_head *jh)
{
- struct buffer_head *bh = jh2bh(jh);
int jlist;
- if (buffer_dirty(bh)) {
- /* If this buffer is one which might reasonably be dirty
- * --- ie. data, or not part of this journal --- then
- * we're OK to leave it alone, but otherwise we need to
- * move the dirty bit to the journal's own internal
- * JBDDirty bit. */
- jlist = jh->b_jlist;
-
- if (jlist == BJ_Metadata || jlist == BJ_Reserved ||
- jlist == BJ_Shadow || jlist == BJ_Forget) {
- if (test_clear_buffer_dirty(jh2bh(jh))) {
- set_bit(BH_JBDDirty, &jh2bh(jh)->b_state);
- }
- }
+ /* If this buffer is one which might reasonably be dirty
+ * --- ie. data, or not part of this journal --- then
+ * we're OK to leave it alone, but otherwise we need to
+ * move the dirty bit to the journal's own internal
+ * JBDDirty bit. */
+ jlist = jh->b_jlist;
+
+ if (jlist == BJ_Metadata || jlist == BJ_Reserved ||
+ jlist == BJ_Shadow || jlist == BJ_Forget) {
+ struct buffer_head *bh = jh2bh(jh);
+
+ if (test_clear_buffer_dirty(bh))
+ set_buffer_jbddirty(bh);
}
}
@@ -574,9 +572,14 @@ repeat:
if (jh->b_next_transaction)
J_ASSERT_JH(jh, jh->b_next_transaction ==
transaction);
- JBUFFER_TRACE(jh, "Unexpected dirty buffer");
- jbd_unexpected_dirty_buffer(jh);
- }
+ }
+ /*
+ * In any case we need to clean the dirty flag and we must
+ * do it under the buffer lock to be sure we don't race
+ * with running write-out.
+ */
+ JBUFFER_TRACE(jh, "Unexpected dirty buffer");
+ jbd_unexpected_dirty_buffer(jh);
}
unlock_buffer(bh);
OpenPOWER on IntegriCloud