git://ftp.safe.ca
/
safe
/
jmp
/
linux-2.6
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
fs/jbd: Export log_start_commit to fix ext3 build.
[safe/jmp/linux-2.6]
/
fs
/
jbd
/
journal.c
diff --git
a/fs/jbd/journal.c
b/fs/jbd/journal.c
index
9816293
..
4160afa
100644
(file)
--- a/
fs/jbd/journal.c
+++ b/
fs/jbd/journal.c
@@
-68,12
+68,12
@@
EXPORT_SYMBOL(journal_set_features);
EXPORT_SYMBOL(journal_create);
EXPORT_SYMBOL(journal_load);
EXPORT_SYMBOL(journal_destroy);
EXPORT_SYMBOL(journal_create);
EXPORT_SYMBOL(journal_load);
EXPORT_SYMBOL(journal_destroy);
-EXPORT_SYMBOL(journal_update_superblock);
EXPORT_SYMBOL(journal_abort);
EXPORT_SYMBOL(journal_errno);
EXPORT_SYMBOL(journal_ack_err);
EXPORT_SYMBOL(journal_clear_err);
EXPORT_SYMBOL(log_wait_commit);
EXPORT_SYMBOL(journal_abort);
EXPORT_SYMBOL(journal_errno);
EXPORT_SYMBOL(journal_ack_err);
EXPORT_SYMBOL(journal_clear_err);
EXPORT_SYMBOL(log_wait_commit);
+EXPORT_SYMBOL(log_start_commit);
EXPORT_SYMBOL(journal_start_commit);
EXPORT_SYMBOL(journal_force_commit_nested);
EXPORT_SYMBOL(journal_wipe);
EXPORT_SYMBOL(journal_start_commit);
EXPORT_SYMBOL(journal_force_commit_nested);
EXPORT_SYMBOL(journal_wipe);
@@
-277,7
+277,7
@@
static void journal_kill_thread(journal_t *journal)
int journal_write_metadata_buffer(transaction_t *transaction,
struct journal_head *jh_in,
struct journal_head **jh_out,
int journal_write_metadata_buffer(transaction_t *transaction,
struct journal_head *jh_in,
struct journal_head **jh_out,
- unsigned
long
blocknr)
+ unsigned
int
blocknr)
{
int need_copy_out = 0;
int done_copy_out = 0;
{
int need_copy_out = 0;
int done_copy_out = 0;
@@
-288,6
+288,7
@@
int journal_write_metadata_buffer(transaction_t *transaction,
struct page *new_page;
unsigned int new_offset;
struct buffer_head *bh_in = jh2bh(jh_in);
struct page *new_page;
unsigned int new_offset;
struct buffer_head *bh_in = jh2bh(jh_in);
+ journal_t *journal = transaction->t_journal;
/*
* The buffer really shouldn't be locked: only the current committing
/*
* The buffer really shouldn't be locked: only the current committing
@@
-301,6
+302,11
@@
int journal_write_metadata_buffer(transaction_t *transaction,
J_ASSERT_BH(bh_in, buffer_jbddirty(bh_in));
new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL);
J_ASSERT_BH(bh_in, buffer_jbddirty(bh_in));
new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL);
+ /* keep subsequent assertions sane */
+ new_bh->b_state = 0;
+ init_buffer(new_bh, NULL, NULL);
+ atomic_set(&new_bh->b_count, 1);
+ new_jh = journal_add_journal_head(new_bh); /* This sleeps */
/*
* If a new transaction has already done a buffer copy-out, then
/*
* If a new transaction has already done a buffer copy-out, then
@@
-362,14
+368,6
@@
repeat:
kunmap_atomic(mapped_data, KM_USER0);
}
kunmap_atomic(mapped_data, KM_USER0);
}
- /* keep subsequent assertions sane */
- new_bh->b_state = 0;
- init_buffer(new_bh, NULL, NULL);
- atomic_set(&new_bh->b_count, 1);
- jbd_unlock_bh_state(bh_in);
-
- new_jh = journal_add_journal_head(new_bh); /* This sleeps */
-
set_bh_page(new_bh, new_page, new_offset);
new_jh->b_transaction = NULL;
new_bh->b_size = jh2bh(jh_in)->b_size;
set_bh_page(new_bh, new_page, new_offset);
new_jh->b_transaction = NULL;
new_bh->b_size = jh2bh(jh_in)->b_size;
@@
-386,7
+384,11
@@
repeat:
* copying is moved to the transaction's shadow queue.
*/
JBUFFER_TRACE(jh_in, "file as BJ_Shadow");
* copying is moved to the transaction's shadow queue.
*/
JBUFFER_TRACE(jh_in, "file as BJ_Shadow");
- journal_file_buffer(jh_in, transaction, BJ_Shadow);
+ spin_lock(&journal->j_list_lock);
+ __journal_file_buffer(jh_in, transaction, BJ_Shadow);
+ spin_unlock(&journal->j_list_lock);
+ jbd_unlock_bh_state(bh_in);
+
JBUFFER_TRACE(new_jh, "file as BJ_IO");
journal_file_buffer(new_jh, transaction, BJ_IO);
JBUFFER_TRACE(new_jh, "file as BJ_IO");
journal_file_buffer(new_jh, transaction, BJ_IO);
@@
-428,7
+430,7
@@
int __log_space_left(journal_t *journal)
}
/*
}
/*
- * Called under j_state_lock. Returns true if a transaction was started.
+ * Called under j_state_lock. Returns true if a transaction
commit
was started.
*/
int __log_start_commit(journal_t *journal, tid_t target)
{
*/
int __log_start_commit(journal_t *journal, tid_t target)
{
@@
-496,7
+498,8
@@
int journal_force_commit_nested(journal_t *journal)
/*
* Start a commit of the current running transaction (if any). Returns true
/*
* Start a commit of the current running transaction (if any). Returns true
- * if a transaction was started, and fills its tid in at *ptid
+ * if a transaction is going to be committed (or is currently already
+ * committing), and fills its tid in at *ptid
*/
int journal_start_commit(journal_t *journal, tid_t *ptid)
{
*/
int journal_start_commit(journal_t *journal, tid_t *ptid)
{
@@
-506,15
+509,19
@@
int journal_start_commit(journal_t *journal, tid_t *ptid)
if (journal->j_running_transaction) {
tid_t tid = journal->j_running_transaction->t_tid;
if (journal->j_running_transaction) {
tid_t tid = journal->j_running_transaction->t_tid;
- ret = __log_start_commit(journal, tid);
- if (ret && ptid)
+ __log_start_commit(journal, tid);
+ /* There's a running transaction and we've just made sure
+ * it's commit has been scheduled. */
+ if (ptid)
*ptid = tid;
*ptid = tid;
- } else if (journal->j_committing_transaction && ptid) {
+ ret = 1;
+ } else if (journal->j_committing_transaction) {
/*
* If ext3_write_super() recently started a commit, then we
* have to wait for completion of that transaction
*/
/*
* If ext3_write_super() recently started a commit, then we
* have to wait for completion of that transaction
*/
- *ptid = journal->j_committing_transaction->t_tid;
+ if (ptid)
+ *ptid = journal->j_committing_transaction->t_tid;
ret = 1;
}
spin_unlock(&journal->j_state_lock);
ret = 1;
}
spin_unlock(&journal->j_state_lock);
@@
-534,7
+541,7
@@
int log_wait_commit(journal_t *journal, tid_t tid)
if (!tid_geq(journal->j_commit_request, tid)) {
printk(KERN_EMERG
"%s: error: j_commit_request=%d, tid=%d\n",
if (!tid_geq(journal->j_commit_request, tid)) {
printk(KERN_EMERG
"%s: error: j_commit_request=%d, tid=%d\n",
- __
FUNCTION
__, journal->j_commit_request, tid);
+ __
func
__, journal->j_commit_request, tid);
}
spin_unlock(&journal->j_state_lock);
#endif
}
spin_unlock(&journal->j_state_lock);
#endif
@@
-561,9
+568,9
@@
int log_wait_commit(journal_t *journal, tid_t tid)
* Log buffer allocation routines:
*/
* Log buffer allocation routines:
*/
-int journal_next_log_block(journal_t *journal, unsigned
long
*retp)
+int journal_next_log_block(journal_t *journal, unsigned
int
*retp)
{
{
- unsigned
long
blocknr;
+ unsigned
int
blocknr;
spin_lock(&journal->j_state_lock);
J_ASSERT(journal->j_free > 1);
spin_lock(&journal->j_state_lock);
J_ASSERT(journal->j_free > 1);
@@
-584,11
+591,11
@@
int journal_next_log_block(journal_t *journal, unsigned long *retp)
* this is a no-op. If needed, we can use j_blk_offset - everything is
* ready.
*/
* this is a no-op. If needed, we can use j_blk_offset - everything is
* ready.
*/
-int journal_bmap(journal_t *journal, unsigned
long
blocknr,
- unsigned
long
*retp)
+int journal_bmap(journal_t *journal, unsigned
int
blocknr,
+ unsigned
int
*retp)
{
int err = 0;
{
int err = 0;
- unsigned
long
ret;
+ unsigned
int
ret;
if (journal->j_inode) {
ret = bmap(journal->j_inode, blocknr);
if (journal->j_inode) {
ret = bmap(journal->j_inode, blocknr);
@@
-598,8
+605,8
@@
int journal_bmap(journal_t *journal, unsigned long blocknr,
char b[BDEVNAME_SIZE];
printk(KERN_ALERT "%s: journal block not found "
char b[BDEVNAME_SIZE];
printk(KERN_ALERT "%s: journal block not found "
- "at offset %
l
u on %s\n",
- __
FUNCTION
__,
+ "at offset %u on %s\n",
+ __
func
__,
blocknr,
bdevname(journal->j_dev, b));
err = -EIO;
blocknr,
bdevname(journal->j_dev, b));
err = -EIO;
@@
-624,7
+631,7
@@
int journal_bmap(journal_t *journal, unsigned long blocknr,
struct journal_head *journal_get_descriptor_buffer(journal_t *journal)
{
struct buffer_head *bh;
struct journal_head *journal_get_descriptor_buffer(journal_t *journal)
{
struct buffer_head *bh;
- unsigned
long
blocknr;
+ unsigned
int
blocknr;
int err;
err = journal_next_log_block(journal, &blocknr);
int err;
err = journal_next_log_block(journal, &blocknr);
@@
-633,6
+640,8
@@
struct journal_head *journal_get_descriptor_buffer(journal_t *journal)
return NULL;
bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
return NULL;
bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
+ if (!bh)
+ return NULL;
lock_buffer(bh);
memset(bh->b_data, 0, journal->j_blocksize);
set_buffer_uptodate(bh);
lock_buffer(bh);
memset(bh->b_data, 0, journal->j_blocksize);
set_buffer_uptodate(bh);
@@
-728,10
+737,8
@@
journal_t * journal_init_dev(struct block_device *bdev,
journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
if (!journal->j_wbuf) {
printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
if (!journal->j_wbuf) {
printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
- __FUNCTION__);
- kfree(journal);
- journal = NULL;
- goto out;
+ __func__);
+ goto out_err;
}
journal->j_dev = bdev;
journal->j_fs_dev = fs_dev;
}
journal->j_dev = bdev;
journal->j_fs_dev = fs_dev;
@@
-739,11
+746,20
@@
journal_t * journal_init_dev(struct block_device *bdev,
journal->j_maxlen = len;
bh = __getblk(journal->j_dev, start, journal->j_blocksize);
journal->j_maxlen = len;
bh = __getblk(journal->j_dev, start, journal->j_blocksize);
- J_ASSERT(bh != NULL);
+ if (!bh) {
+ printk(KERN_ERR
+ "%s: Cannot get buffer for journal superblock\n",
+ __func__);
+ goto out_err;
+ }
journal->j_sb_buffer = bh;
journal->j_superblock = (journal_superblock_t *)bh->b_data;
journal->j_sb_buffer = bh;
journal->j_superblock = (journal_superblock_t *)bh->b_data;
-out:
+
return journal;
return journal;
+out_err:
+ kfree(journal->j_wbuf);
+ kfree(journal);
+ return NULL;
}
/**
}
/**
@@
-760,7
+776,7
@@
journal_t * journal_init_inode (struct inode *inode)
journal_t *journal = journal_init_common();
int err;
int n;
journal_t *journal = journal_init_common();
int err;
int n;
- unsigned
long
blocknr;
+ unsigned
int
blocknr;
if (!journal)
return NULL;
if (!journal)
return NULL;
@@
-782,26
+798,33
@@
journal_t * journal_init_inode (struct inode *inode)
journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
if (!journal->j_wbuf) {
printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
if (!journal->j_wbuf) {
printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
- __FUNCTION__);
- kfree(journal);
- return NULL;
+ __func__);
+ goto out_err;
}
err = journal_bmap(journal, 0, &blocknr);
/* If that failed, give up */
if (err) {
printk(KERN_ERR "%s: Cannnot locate journal superblock\n",
}
err = journal_bmap(journal, 0, &blocknr);
/* If that failed, give up */
if (err) {
printk(KERN_ERR "%s: Cannnot locate journal superblock\n",
- __FUNCTION__);
- kfree(journal);
- return NULL;
+ __func__);
+ goto out_err;
}
bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
}
bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
- J_ASSERT(bh != NULL);
+ if (!bh) {
+ printk(KERN_ERR
+ "%s: Cannot get buffer for journal superblock\n",
+ __func__);
+ goto out_err;
+ }
journal->j_sb_buffer = bh;
journal->j_superblock = (journal_superblock_t *)bh->b_data;
return journal;
journal->j_sb_buffer = bh;
journal->j_superblock = (journal_superblock_t *)bh->b_data;
return journal;
+out_err:
+ kfree(journal->j_wbuf);
+ kfree(journal);
+ return NULL;
}
/*
}
/*
@@
-826,10
+849,16
@@
static void journal_fail_superblock (journal_t *journal)
static int journal_reset(journal_t *journal)
{
journal_superblock_t *sb = journal->j_superblock;
static int journal_reset(journal_t *journal)
{
journal_superblock_t *sb = journal->j_superblock;
- unsigned
long
first, last;
+ unsigned
int
first, last;
first = be32_to_cpu(sb->s_first);
last = be32_to_cpu(sb->s_maxlen);
first = be32_to_cpu(sb->s_first);
last = be32_to_cpu(sb->s_maxlen);
+ if (first + JFS_MIN_JOURNAL_BLOCKS > last + 1) {
+ printk(KERN_ERR "JBD: Journal too short (blocks %u-%u).\n",
+ first, last);
+ journal_fail_superblock(journal);
+ return -EINVAL;
+ }
journal->j_first = first;
journal->j_last = last;
journal->j_first = first;
journal->j_last = last;
@@
-859,7
+888,7
@@
static int journal_reset(journal_t *journal)
**/
int journal_create(journal_t *journal)
{
**/
int journal_create(journal_t *journal)
{
- unsigned
long
blocknr;
+ unsigned
int
blocknr;
struct buffer_head *bh;
journal_superblock_t *sb;
int i, err;
struct buffer_head *bh;
journal_superblock_t *sb;
int i, err;
@@
-877,7
+906,7
@@
int journal_create(journal_t *journal)
*/
printk(KERN_EMERG
"%s: creation of journal on external device!\n",
*/
printk(KERN_EMERG
"%s: creation of journal on external device!\n",
- __
FUNCTION
__);
+ __
func
__);
BUG();
}
BUG();
}
@@
-943,14
+972,14
@@
void journal_update_superblock(journal_t *journal, int wait)
if (sb->s_start == 0 && journal->j_tail_sequence ==
journal->j_transaction_sequence) {
jbd_debug(1,"JBD: Skipping superblock update on recovered sb "
if (sb->s_start == 0 && journal->j_tail_sequence ==
journal->j_transaction_sequence) {
jbd_debug(1,"JBD: Skipping superblock update on recovered sb "
- "(start %
ld
, seq %d, errno %d)\n",
+ "(start %
u
, seq %d, errno %d)\n",
journal->j_tail, journal->j_tail_sequence,
journal->j_errno);
goto out;
}
spin_lock(&journal->j_state_lock);
journal->j_tail, journal->j_tail_sequence,
journal->j_errno);
goto out;
}
spin_lock(&journal->j_state_lock);
- jbd_debug(1,"JBD: updating superblock (start %
ld
, seq %d, errno %d)\n",
+ jbd_debug(1,"JBD: updating superblock (start %
u
, seq %d, errno %d)\n",
journal->j_tail, journal->j_tail_sequence, journal->j_errno);
sb->s_sequence = cpu_to_be32(journal->j_tail_sequence);
journal->j_tail, journal->j_tail_sequence, journal->j_errno);
sb->s_sequence = cpu_to_be32(journal->j_tail_sequence);
@@
-1122,9
+1151,12
@@
recovery_error:
*
* Release a journal_t structure once it is no longer in use by the
* journaled object.
*
* Release a journal_t structure once it is no longer in use by the
* journaled object.
+ * Return <0 if we couldn't clean up the journal.
*/
*/
-
void
journal_destroy(journal_t *journal)
+
int
journal_destroy(journal_t *journal)
{
{
+ int err = 0;
+
/* Wait for the commit thread to wake up and die. */
journal_kill_thread(journal);
/* Wait for the commit thread to wake up and die. */
journal_kill_thread(journal);
@@
-1147,11
+1179,16
@@
void journal_destroy(journal_t *journal)
J_ASSERT(journal->j_checkpoint_transactions == NULL);
spin_unlock(&journal->j_list_lock);
J_ASSERT(journal->j_checkpoint_transactions == NULL);
spin_unlock(&journal->j_list_lock);
- /* We can now mark the journal as empty. */
- journal->j_tail = 0;
- journal->j_tail_sequence = ++journal->j_transaction_sequence;
if (journal->j_sb_buffer) {
if (journal->j_sb_buffer) {
- journal_update_superblock(journal, 1);
+ if (!is_journal_aborted(journal)) {
+ /* We can now mark the journal as empty. */
+ journal->j_tail = 0;
+ journal->j_tail_sequence =
+ ++journal->j_transaction_sequence;
+ journal_update_superblock(journal, 1);
+ } else {
+ err = -EIO;
+ }
brelse(journal->j_sb_buffer);
}
brelse(journal->j_sb_buffer);
}
@@
-1161,6
+1198,8
@@
void journal_destroy(journal_t *journal)
journal_destroy_revoke(journal);
kfree(journal->j_wbuf);
kfree(journal);
journal_destroy_revoke(journal);
kfree(journal->j_wbuf);
kfree(journal);
+
+ return err;
}
}
@@
-1335,7
+1374,7
@@
int journal_flush(journal_t *journal)
{
int err = 0;
transaction_t *transaction = NULL;
{
int err = 0;
transaction_t *transaction = NULL;
- unsigned
long
old_tail;
+ unsigned
int
old_tail;
spin_lock(&journal->j_state_lock);
spin_lock(&journal->j_state_lock);
@@
-1360,10
+1399,16
@@
int journal_flush(journal_t *journal)
spin_lock(&journal->j_list_lock);
while (!err && journal->j_checkpoint_transactions != NULL) {
spin_unlock(&journal->j_list_lock);
spin_lock(&journal->j_list_lock);
while (!err && journal->j_checkpoint_transactions != NULL) {
spin_unlock(&journal->j_list_lock);
+ mutex_lock(&journal->j_checkpoint_mutex);
err = log_do_checkpoint(journal);
err = log_do_checkpoint(journal);
+ mutex_unlock(&journal->j_checkpoint_mutex);
spin_lock(&journal->j_list_lock);
}
spin_unlock(&journal->j_list_lock);
spin_lock(&journal->j_list_lock);
}
spin_unlock(&journal->j_list_lock);
+
+ if (is_journal_aborted(journal))
+ return -EIO;
+
cleanup_journal_tail(journal);
/* Finally, mark the journal as really needing no recovery.
cleanup_journal_tail(journal);
/* Finally, mark the journal as really needing no recovery.
@@
-1385,7
+1430,7
@@
int journal_flush(journal_t *journal)
J_ASSERT(journal->j_head == journal->j_tail);
J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence);
spin_unlock(&journal->j_state_lock);
J_ASSERT(journal->j_head == journal->j_tail);
J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence);
spin_unlock(&journal->j_state_lock);
- return
err
;
+ return
0
;
}
/**
}
/**
@@
-1620,14
+1665,14
@@
static int journal_init_journal_head_cache(void)
{
int retval;
{
int retval;
- J_ASSERT(journal_head_cache ==
0
);
+ J_ASSERT(journal_head_cache ==
NULL
);
journal_head_cache = kmem_cache_create("journal_head",
sizeof(struct journal_head),
0, /* offset */
SLAB_TEMPORARY, /* flags */
NULL); /* ctor */
retval = 0;
journal_head_cache = kmem_cache_create("journal_head",
sizeof(struct journal_head),
0, /* offset */
SLAB_TEMPORARY, /* flags */
NULL); /* ctor */
retval = 0;
- if (
journal_head_cache == 0
) {
+ if (
!journal_head_cache
) {
retval = -ENOMEM;
printk(KERN_EMERG "JBD: no memory for journal_head cache\n");
}
retval = -ENOMEM;
printk(KERN_EMERG "JBD: no memory for journal_head cache\n");
}
@@
-1636,9
+1681,10
@@
static int journal_init_journal_head_cache(void)
static void journal_destroy_journal_head_cache(void)
{
static void journal_destroy_journal_head_cache(void)
{
- J_ASSERT(journal_head_cache != NULL);
- kmem_cache_destroy(journal_head_cache);
- journal_head_cache = NULL;
+ if (journal_head_cache) {
+ kmem_cache_destroy(journal_head_cache);
+ journal_head_cache = NULL;
+ }
}
/*
}
/*
@@
-1657,7
+1703,7
@@
static struct journal_head *journal_alloc_journal_head(void)
jbd_debug(1, "out of memory for journal_head\n");
if (time_after(jiffies, last_warning + 5*HZ)) {
printk(KERN_NOTICE "ENOMEM in %s, retrying.\n",
jbd_debug(1, "out of memory for journal_head\n");
if (time_after(jiffies, last_warning + 5*HZ)) {
printk(KERN_NOTICE "ENOMEM in %s, retrying.\n",
- __
FUNCTION
__);
+ __
func
__);
last_warning = jiffies;
}
while (ret == NULL) {
last_warning = jiffies;
}
while (ret == NULL) {
@@
-1794,13
+1840,13
@@
static void __journal_remove_journal_head(struct buffer_head *bh)
if (jh->b_frozen_data) {
printk(KERN_WARNING "%s: freeing "
"b_frozen_data\n",
if (jh->b_frozen_data) {
printk(KERN_WARNING "%s: freeing "
"b_frozen_data\n",
- __
FUNCTION
__);
+ __
func
__);
jbd_free(jh->b_frozen_data, bh->b_size);
}
if (jh->b_committed_data) {
printk(KERN_WARNING "%s: freeing "
"b_committed_data\n",
jbd_free(jh->b_frozen_data, bh->b_size);
}
if (jh->b_committed_data) {
printk(KERN_WARNING "%s: freeing "
"b_committed_data\n",
- __
FUNCTION
__);
+ __
func
__);
jbd_free(jh->b_committed_data, bh->b_size);
}
bh->b_private = NULL;
jbd_free(jh->b_committed_data, bh->b_size);
}
bh->b_private = NULL;