2017-12-18 06:00:59 +03:00
// SPDX-License-Identifier: GPL-2.0+
2006-10-11 12:20:57 +04:00
/*
2007-05-09 09:51:49 +04:00
* linux / fs / jbd2 / checkpoint . c
2006-10-11 12:20:57 +04:00
*
* Written by Stephen C . Tweedie < sct @ redhat . com > , 1999
*
* Copyright 1999 Red Hat Software - - - All Rights Reserved
*
* Checkpoint routines for the generic filesystem journaling code .
* Part of the ext2fs journaling system .
*
* Checkpointing is the process of ensuring that a section of the log is
* committed fully to disk , so that that portion of the log can be
* reused .
*/
# include <linux/time.h>
# include <linux/fs.h>
2006-10-11 12:20:59 +04:00
# include <linux/jbd2.h>
2006-10-11 12:20:57 +04:00
# include <linux/errno.h>
# include <linux/slab.h>
2009-12-23 14:52:08 +03:00
# include <linux/blkdev.h>
2009-06-17 19:47:48 +04:00
# include <trace/events/jbd2.h>
2006-10-11 12:20:57 +04:00
/*
* Unlink a buffer from a transaction checkpoint list .
*
* Called with j_list_lock held .
*/
static inline void __buffer_unlink_first ( struct journal_head * jh )
{
transaction_t * transaction = jh - > b_cp_transaction ;
jh - > b_cpnext - > b_cpprev = jh - > b_cpprev ;
jh - > b_cpprev - > b_cpnext = jh - > b_cpnext ;
if ( transaction - > t_checkpoint_list = = jh ) {
transaction - > t_checkpoint_list = jh - > b_cpnext ;
if ( transaction - > t_checkpoint_list = = jh )
transaction - > t_checkpoint_list = NULL ;
}
}
/*
* Unlink a buffer from a transaction checkpoint ( io ) list .
*
* Called with j_list_lock held .
*/
static inline void __buffer_unlink ( struct journal_head * jh )
{
transaction_t * transaction = jh - > b_cp_transaction ;
__buffer_unlink_first ( jh ) ;
if ( transaction - > t_checkpoint_io_list = = jh ) {
transaction - > t_checkpoint_io_list = jh - > b_cpnext ;
if ( transaction - > t_checkpoint_io_list = = jh )
transaction - > t_checkpoint_io_list = NULL ;
}
}
/*
* Move a buffer from the checkpoint list to the checkpoint io list
*
* Called with j_list_lock held
*/
static inline void __buffer_relink_io ( struct journal_head * jh )
{
transaction_t * transaction = jh - > b_cp_transaction ;
__buffer_unlink_first ( jh ) ;
if ( ! transaction - > t_checkpoint_io_list ) {
jh - > b_cpnext = jh - > b_cpprev = jh ;
} else {
jh - > b_cpnext = transaction - > t_checkpoint_io_list ;
jh - > b_cpprev = transaction - > t_checkpoint_io_list - > b_cpprev ;
jh - > b_cpprev - > b_cpnext = jh ;
jh - > b_cpnext - > b_cpprev = jh ;
}
transaction - > t_checkpoint_io_list = jh ;
}
/*
* Try to release a checkpointed buffer from its transaction .
* Returns 1 if we released it and 2 if we also released the
* whole transaction .
*
* Requires j_list_lock
*/
static int __try_to_free_cp_buf ( struct journal_head * jh )
{
int ret = 0 ;
struct buffer_head * bh = jh2bh ( jh ) ;
2012-03-14 06:45:25 +04:00
if ( jh - > b_transaction = = NULL & & ! buffer_locked ( bh ) & &
2008-10-11 04:29:13 +04:00
! buffer_dirty ( bh ) & & ! buffer_write_io_error ( bh ) ) {
2006-10-11 12:20:57 +04:00
JBUFFER_TRACE ( jh , " remove from checkpoint list " ) ;
2006-10-11 12:20:59 +04:00
ret = __jbd2_journal_remove_checkpoint ( jh ) + 1 ;
2006-10-11 12:20:57 +04:00
}
return ret ;
}
/*
2006-10-11 12:20:59 +04:00
* __jbd2_log_wait_for_space : wait until there is space in the journal .
2006-10-11 12:20:57 +04:00
*
* Called under j - state_lock * only * . It will be unlocked if we have to wait
* for a checkpoint to free up some space in the log .
*/
2006-10-11 12:20:59 +04:00
void __jbd2_log_wait_for_space ( journal_t * journal )
2020-11-07 08:00:49 +03:00
__acquires ( & journal - > j_state_lock )
__releases ( & journal - > j_state_lock )
2006-10-11 12:20:57 +04:00
{
2008-11-07 06:38:07 +03:00
int nblocks , space_left ;
2010-08-04 05:35:12 +04:00
/* assert_spin_locked(&journal->j_state_lock); */
2006-10-11 12:20:57 +04:00
2019-11-05 19:44:25 +03:00
nblocks = journal - > j_max_transaction_buffers ;
2013-06-04 20:12:57 +04:00
while ( jbd2_log_space_left ( journal ) < nblocks ) {
2010-08-04 05:35:12 +04:00
write_unlock ( & journal - > j_state_lock ) ;
2019-02-01 07:42:11 +03:00
mutex_lock_io ( & journal - > j_checkpoint_mutex ) ;
2006-10-11 12:20:57 +04:00
/*
* Test again , another process may have checkpointed while we
2008-10-09 07:28:31 +04:00
* were waiting for the checkpoint lock . If there are no
2008-11-07 06:38:07 +03:00
* transactions ready to be checkpointed , try to recover
* journal space by calling cleanup_journal_tail ( ) , and if
* that doesn ' t work , by waiting for the currently committing
* transaction to complete . If there is absolutely no way
* to make progress , this is either a BUG or corrupted
* filesystem , so abort the journal and leave a stack
* trace for forensic evidence .
2006-10-11 12:20:57 +04:00
*/
2010-08-04 05:35:12 +04:00
write_lock ( & journal - > j_state_lock ) ;
2014-09-16 22:50:50 +04:00
if ( journal - > j_flags & JBD2_ABORT ) {
mutex_unlock ( & journal - > j_checkpoint_mutex ) ;
return ;
}
2008-10-09 07:28:31 +04:00
spin_lock ( & journal - > j_list_lock ) ;
2013-06-04 20:12:57 +04:00
space_left = jbd2_log_space_left ( journal ) ;
2008-11-07 06:38:07 +03:00
if ( space_left < nblocks ) {
2008-10-09 07:28:31 +04:00
int chkpt = journal - > j_checkpoint_transactions ! = NULL ;
2008-11-07 06:38:07 +03:00
tid_t tid = 0 ;
2008-10-09 07:28:31 +04:00
2008-11-07 06:38:07 +03:00
if ( journal - > j_committing_transaction )
tid = journal - > j_committing_transaction - > t_tid ;
2008-10-09 07:28:31 +04:00
spin_unlock ( & journal - > j_list_lock ) ;
2010-08-04 05:35:12 +04:00
write_unlock ( & journal - > j_state_lock ) ;
2008-10-09 07:28:31 +04:00
if ( chkpt ) {
jbd2_log_do_checkpoint ( journal ) ;
2008-11-07 06:38:07 +03:00
} else if ( jbd2_cleanup_journal_tail ( journal ) = = 0 ) {
/* We were able to recover space; yay! */
;
} else if ( tid ) {
jbd2: drop checkpoint mutex when waiting in __jbd2_log_wait_for_space()
While trying to debug an an issue under extreme I/O loading
on preempt-rt kernels, the following backtrace was observed
via SysRQ output:
rm D ffff8802203afbc0 4600 4878 4748 0x00000000
ffff8802217bfb78 0000000000000082 ffff88021fc2bb80 ffff88021fc2bb80
ffff88021fc2bb80 ffff8802217bffd8 ffff8802217bffd8 ffff8802217bffd8
ffff88021f1d4c80 ffff88021fc2bb80 ffff8802217bfb88 ffff88022437b000
Call Trace:
[<ffffffff8172dc34>] schedule+0x24/0x70
[<ffffffff81225b5d>] jbd2_log_wait_commit+0xbd/0x140
[<ffffffff81060390>] ? __init_waitqueue_head+0x50/0x50
[<ffffffff81223635>] jbd2_log_do_checkpoint+0xf5/0x520
[<ffffffff81223b09>] __jbd2_log_wait_for_space+0xa9/0x1f0
[<ffffffff8121dc40>] start_this_handle.isra.10+0x2e0/0x530
[<ffffffff81060390>] ? __init_waitqueue_head+0x50/0x50
[<ffffffff8121e0a3>] jbd2__journal_start+0xc3/0x110
[<ffffffff811de7ce>] ? ext4_rmdir+0x6e/0x230
[<ffffffff8121e0fe>] jbd2_journal_start+0xe/0x10
[<ffffffff811f308b>] ext4_journal_start_sb+0x5b/0x160
[<ffffffff811de7ce>] ext4_rmdir+0x6e/0x230
[<ffffffff811435c5>] vfs_rmdir+0xd5/0x140
[<ffffffff8114370f>] do_rmdir+0xdf/0x120
[<ffffffff8105c6b4>] ? task_work_run+0x44/0x80
[<ffffffff81002889>] ? do_notify_resume+0x89/0x100
[<ffffffff817361ae>] ? int_signal+0x12/0x17
[<ffffffff81145d85>] sys_unlinkat+0x25/0x40
[<ffffffff81735f22>] system_call_fastpath+0x16/0x1b
What is interesting here, is that we call log_wait_commit, from
within wait_for_space, but we are still holding the checkpoint_mutex
as it surrounds mostly the whole of wait_for_space. And then, as we
are waiting, journal_commit_transaction can run, and if the JBD2_FLUSHED
bit is set, then we will also try to take the same checkpoint_mutex.
It seems that we need to drop the checkpoint_mutex while sitting in
jbd2_log_wait_commit, if we want to guarantee that progress can be made
by jbd2_journal_commit_transaction(). There does not seem to be
anything preempt-rt specific about this, other then perhaps increasing
the odds of it happening.
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2013-06-13 06:47:35 +04:00
/*
* jbd2_journal_commit_transaction ( ) may want
* to take the checkpoint_mutex if JBD2_FLUSHED
* is set . So we need to temporarily drop it .
*/
mutex_unlock ( & journal - > j_checkpoint_mutex ) ;
2008-11-07 06:38:07 +03:00
jbd2_log_wait_commit ( journal , tid ) ;
jbd2: drop checkpoint mutex when waiting in __jbd2_log_wait_for_space()
While trying to debug an an issue under extreme I/O loading
on preempt-rt kernels, the following backtrace was observed
via SysRQ output:
rm D ffff8802203afbc0 4600 4878 4748 0x00000000
ffff8802217bfb78 0000000000000082 ffff88021fc2bb80 ffff88021fc2bb80
ffff88021fc2bb80 ffff8802217bffd8 ffff8802217bffd8 ffff8802217bffd8
ffff88021f1d4c80 ffff88021fc2bb80 ffff8802217bfb88 ffff88022437b000
Call Trace:
[<ffffffff8172dc34>] schedule+0x24/0x70
[<ffffffff81225b5d>] jbd2_log_wait_commit+0xbd/0x140
[<ffffffff81060390>] ? __init_waitqueue_head+0x50/0x50
[<ffffffff81223635>] jbd2_log_do_checkpoint+0xf5/0x520
[<ffffffff81223b09>] __jbd2_log_wait_for_space+0xa9/0x1f0
[<ffffffff8121dc40>] start_this_handle.isra.10+0x2e0/0x530
[<ffffffff81060390>] ? __init_waitqueue_head+0x50/0x50
[<ffffffff8121e0a3>] jbd2__journal_start+0xc3/0x110
[<ffffffff811de7ce>] ? ext4_rmdir+0x6e/0x230
[<ffffffff8121e0fe>] jbd2_journal_start+0xe/0x10
[<ffffffff811f308b>] ext4_journal_start_sb+0x5b/0x160
[<ffffffff811de7ce>] ext4_rmdir+0x6e/0x230
[<ffffffff811435c5>] vfs_rmdir+0xd5/0x140
[<ffffffff8114370f>] do_rmdir+0xdf/0x120
[<ffffffff8105c6b4>] ? task_work_run+0x44/0x80
[<ffffffff81002889>] ? do_notify_resume+0x89/0x100
[<ffffffff817361ae>] ? int_signal+0x12/0x17
[<ffffffff81145d85>] sys_unlinkat+0x25/0x40
[<ffffffff81735f22>] system_call_fastpath+0x16/0x1b
What is interesting here, is that we call log_wait_commit, from
within wait_for_space, but we are still holding the checkpoint_mutex
as it surrounds mostly the whole of wait_for_space. And then, as we
are waiting, journal_commit_transaction can run, and if the JBD2_FLUSHED
bit is set, then we will also try to take the same checkpoint_mutex.
It seems that we need to drop the checkpoint_mutex while sitting in
jbd2_log_wait_commit, if we want to guarantee that progress can be made
by jbd2_journal_commit_transaction(). There does not seem to be
anything preempt-rt specific about this, other then perhaps increasing
the odds of it happening.
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2013-06-13 06:47:35 +04:00
write_lock ( & journal - > j_state_lock ) ;
continue ;
2008-10-09 07:28:31 +04:00
} else {
2008-11-07 06:38:07 +03:00
printk ( KERN_ERR " %s: needed %d blocks and "
" only had %d space available \n " ,
__func__ , nblocks , space_left ) ;
printk ( KERN_ERR " %s: no way to get more "
" journal space in %s \n " , __func__ ,
journal - > j_devname ) ;
WARN_ON ( 1 ) ;
2019-12-04 15:46:12 +03:00
jbd2_journal_abort ( journal , - EIO ) ;
2008-10-09 07:28:31 +04:00
}
2010-08-04 05:35:12 +04:00
write_lock ( & journal - > j_state_lock ) ;
2008-10-09 07:28:31 +04:00
} else {
spin_unlock ( & journal - > j_list_lock ) ;
2006-10-11 12:20:57 +04:00
}
mutex_unlock ( & journal - > j_checkpoint_mutex ) ;
}
}
static void
2008-11-05 08:09:22 +03:00
__flush_batch ( journal_t * journal , int * batch_count )
2006-10-11 12:20:57 +04:00
{
int i ;
2011-06-27 20:36:29 +04:00
struct blk_plug plug ;
2006-10-11 12:20:57 +04:00
2011-06-27 20:36:29 +04:00
blk_start_plug ( & plug ) ;
2010-08-11 19:06:24 +04:00
for ( i = 0 ; i < * batch_count ; i + + )
2016-11-01 16:40:10 +03:00
write_dirty_buffer ( journal - > j_chkpt_bhs [ i ] , REQ_SYNC ) ;
2011-06-27 20:36:29 +04:00
blk_finish_plug ( & plug ) ;
2010-08-11 19:06:24 +04:00
2006-10-11 12:20:57 +04:00
for ( i = 0 ; i < * batch_count ; i + + ) {
2008-11-05 08:09:22 +03:00
struct buffer_head * bh = journal - > j_chkpt_bhs [ i ] ;
2006-10-11 12:20:57 +04:00
BUFFER_TRACE ( bh , " brelse " ) ;
__brelse ( bh ) ;
}
* batch_count = 0 ;
}
/*
* Perform an actual checkpoint . We take the first transaction on the
* list of transactions to be checkpointed and send all its buffers
* to disk . We submit larger chunks of data at once .
*
* The journal should be locked before calling this function .
2008-10-11 04:29:13 +04:00
* Called with j_checkpoint_mutex held .
2006-10-11 12:20:57 +04:00
*/
2006-10-11 12:20:59 +04:00
int jbd2_log_do_checkpoint ( journal_t * journal )
2006-10-11 12:20:57 +04:00
{
2014-09-02 05:19:01 +04:00
struct journal_head * jh ;
struct buffer_head * bh ;
transaction_t * transaction ;
tid_t this_tid ;
2014-09-05 02:09:22 +04:00
int result , batch_count = 0 ;
2006-10-11 12:20:57 +04:00
jbd_debug ( 1 , " Start checkpoint \n " ) ;
/*
* First thing : if there are any transactions in the log which
* don ' t need checkpointing , just eliminate them from the
* journal straight away .
*/
2006-10-11 12:20:59 +04:00
result = jbd2_cleanup_journal_tail ( journal ) ;
2009-06-17 19:47:48 +04:00
trace_jbd2_checkpoint ( journal , result ) ;
2006-10-11 12:20:57 +04:00
jbd_debug ( 1 , " cleanup_journal_tail returned %d \n " , result ) ;
if ( result < = 0 )
return result ;
/*
* OK , we need to start writing disk blocks . Take one transaction
* and write it .
*/
2008-10-11 04:29:13 +04:00
result = 0 ;
2006-10-11 12:20:57 +04:00
spin_lock ( & journal - > j_list_lock ) ;
if ( ! journal - > j_checkpoint_transactions )
goto out ;
transaction = journal - > j_checkpoint_transactions ;
2008-01-29 07:58:27 +03:00
if ( transaction - > t_chp_stats . cs_chp_time = = 0 )
transaction - > t_chp_stats . cs_chp_time = jiffies ;
2006-10-11 12:20:57 +04:00
this_tid = transaction - > t_tid ;
restart :
/*
* If someone cleaned up this transaction while we slept , we ' re
* done ( maybe it ' s a new transaction , but it fell at the same
* address ) .
*/
2014-09-02 05:19:01 +04:00
if ( journal - > j_checkpoint_transactions ! = transaction | |
transaction - > t_tid ! = this_tid )
goto out ;
2006-10-11 12:20:57 +04:00
2014-09-02 05:19:01 +04:00
/* checkpoint all of the transaction's buffers */
while ( transaction - > t_checkpoint_list ) {
jh = transaction - > t_checkpoint_list ;
bh = jh2bh ( jh ) ;
if ( buffer_locked ( bh ) ) {
get_bh ( bh ) ;
2018-10-06 01:44:40 +03:00
spin_unlock ( & journal - > j_list_lock ) ;
2014-09-02 05:19:01 +04:00
wait_on_buffer ( bh ) ;
/* the journal_head may have gone by now */
BUFFER_TRACE ( bh , " brelse " ) ;
__brelse ( bh ) ;
goto retry ;
2006-10-11 12:20:57 +04:00
}
2014-09-02 05:19:01 +04:00
if ( jh - > b_transaction ! = NULL ) {
transaction_t * t = jh - > b_transaction ;
tid_t tid = t - > t_tid ;
2006-10-11 12:20:57 +04:00
2014-09-02 05:19:01 +04:00
transaction - > t_chp_stats . cs_forced_to_close + + ;
spin_unlock ( & journal - > j_list_lock ) ;
if ( unlikely ( journal - > j_flags & JBD2_UNMOUNT ) )
/*
* The journal thread is dead ; so
* starting and waiting for a commit
* to finish will cause us to wait for
* a _very_ long time .
*/
printk ( KERN_ERR
" JBD2: %s: Waiting for Godot: block %llu \n " ,
journal - > j_devname , ( unsigned long long ) bh - > b_blocknr ) ;
2019-02-01 07:42:11 +03:00
if ( batch_count )
__flush_batch ( journal , & batch_count ) ;
2014-09-02 05:19:01 +04:00
jbd2_log_start_commit ( journal , tid ) ;
2019-02-01 07:42:11 +03:00
/*
* jbd2_journal_commit_transaction ( ) may want
* to take the checkpoint_mutex if JBD2_FLUSHED
* is set , jbd2_update_log_tail ( ) called by
* jbd2_journal_commit_transaction ( ) may also take
* checkpoint_mutex . So we need to temporarily
* drop it .
*/
mutex_unlock ( & journal - > j_checkpoint_mutex ) ;
2014-09-02 05:19:01 +04:00
jbd2_log_wait_commit ( journal , tid ) ;
2019-02-01 07:42:11 +03:00
mutex_lock_io ( & journal - > j_checkpoint_mutex ) ;
spin_lock ( & journal - > j_list_lock ) ;
goto restart ;
2014-09-02 05:19:01 +04:00
}
if ( ! buffer_dirty ( bh ) ) {
if ( unlikely ( buffer_write_io_error ( bh ) ) & & ! result )
result = - EIO ;
BUFFER_TRACE ( bh , " remove from checkpoint " ) ;
2014-09-05 02:09:29 +04:00
if ( __jbd2_journal_remove_checkpoint ( jh ) )
/* The transaction was released; we're done */
goto out ;
continue ;
2006-10-11 12:20:57 +04:00
}
/*
2014-09-02 05:19:01 +04:00
* Important : we are about to write the buffer , and
* possibly block , while still holding the journal
* lock . We cannot afford to let the transaction
* logic start messing around with this buffer before
* we write it to disk , as that would break
* recoverability .
2006-10-11 12:20:57 +04:00
*/
2014-09-02 05:19:01 +04:00
BUFFER_TRACE ( bh , " queue " ) ;
get_bh ( bh ) ;
J_ASSERT_BH ( bh , ! buffer_jwrite ( bh ) ) ;
journal - > j_chkpt_bhs [ batch_count + + ] = bh ;
__buffer_relink_io ( jh ) ;
transaction - > t_chp_stats . cs_written + + ;
if ( ( batch_count = = JBD2_NR_BATCH ) | |
need_resched ( ) | |
spin_needbreak ( & journal - > j_list_lock ) )
goto unlock_and_flush ;
2006-10-11 12:20:57 +04:00
}
2014-09-02 05:19:01 +04:00
if ( batch_count ) {
unlock_and_flush :
spin_unlock ( & journal - > j_list_lock ) ;
retry :
if ( batch_count )
__flush_batch ( journal , & batch_count ) ;
spin_lock ( & journal - > j_list_lock ) ;
goto restart ;
}
/*
* Now we issued all of the transaction ' s buffers , let ' s deal
* with the buffers that are out for I / O .
*/
2014-09-02 05:26:09 +04:00
restart2 :
/* Did somebody clean up the transaction in the meanwhile? */
if ( journal - > j_checkpoint_transactions ! = transaction | |
transaction - > t_tid ! = this_tid )
goto out ;
2014-09-05 02:09:22 +04:00
while ( transaction - > t_checkpoint_io_list ) {
2014-09-02 05:26:09 +04:00
jh = transaction - > t_checkpoint_io_list ;
bh = jh2bh ( jh ) ;
if ( buffer_locked ( bh ) ) {
2014-09-05 02:09:22 +04:00
get_bh ( bh ) ;
2018-10-06 01:44:40 +03:00
spin_unlock ( & journal - > j_list_lock ) ;
2014-09-02 05:26:09 +04:00
wait_on_buffer ( bh ) ;
/* the journal_head may have gone by now */
BUFFER_TRACE ( bh , " brelse " ) ;
__brelse ( bh ) ;
spin_lock ( & journal - > j_list_lock ) ;
goto restart2 ;
}
if ( unlikely ( buffer_write_io_error ( bh ) ) & & ! result )
result = - EIO ;
/*
* Now in whatever state the buffer currently is , we
* know that it has been written out and so we can
* drop it from the list
*/
2014-09-05 02:09:22 +04:00
if ( __jbd2_journal_remove_checkpoint ( jh ) )
break ;
2014-09-02 05:26:09 +04:00
}
2006-10-11 12:20:57 +04:00
out :
spin_unlock ( & journal - > j_list_lock ) ;
if ( result < 0 )
2008-10-11 04:29:13 +04:00
jbd2_journal_abort ( journal , result ) ;
else
result = jbd2_cleanup_journal_tail ( journal ) ;
return ( result < 0 ) ? result : 0 ;
2006-10-11 12:20:57 +04:00
}
/*
* Check the list of checkpoint transactions for the journal to see if
* we have already got rid of any since the last update of the log tail
* in the journal superblock . If so , we can instantly roll the
* superblock forward to remove those transactions from the log .
*
* Return < 0 on error , 0 on success , 1 if there was nothing to clean up .
*
* Called with the journal lock held .
*
* This is the only part of the journaling code which really needs to be
* aware of transaction aborts . Checkpointing involves writing to the
* main filesystem area rather than to the journal , so it can proceed
2008-10-11 04:29:13 +04:00
* even in abort state , but we must not update the super block if
* checkpointing may have failed . Otherwise , we would lose some metadata
* buffers which should be written - back to the filesystem .
2006-10-11 12:20:57 +04:00
*/
2006-10-11 12:20:59 +04:00
int jbd2_cleanup_journal_tail ( journal_t * journal )
2006-10-11 12:20:57 +04:00
{
tid_t first_tid ;
2012-03-14 06:22:54 +04:00
unsigned long blocknr ;
2006-10-11 12:20:57 +04:00
2008-10-11 04:29:13 +04:00
if ( is_journal_aborted ( journal ) )
2015-06-15 21:36:01 +03:00
return - EIO ;
2008-10-11 04:29:13 +04:00
2012-03-14 06:22:54 +04:00
if ( ! jbd2_journal_get_log_tail ( journal , & first_tid , & blocknr ) )
2006-10-11 12:20:57 +04:00
return 1 ;
2012-03-14 06:22:54 +04:00
J_ASSERT ( blocknr ! = 0 ) ;
2009-12-23 14:52:08 +03:00
/*
2012-03-14 06:22:54 +04:00
* We need to make sure that any blocks that were recently written out
* - - - perhaps by jbd2_log_do_checkpoint ( ) - - - are flushed out before
* we drop the transactions from the journal . It ' s unlikely this will
* be necessary , especially with an appropriately sized journal , but we
* need this to guarantee correctness . Fortunately
* jbd2_cleanup_journal_tail ( ) doesn ' t get called all that often .
2009-12-23 14:52:08 +03:00
*/
2012-03-14 06:22:54 +04:00
if ( journal - > j_flags & JBD2_BARRIER )
2021-01-26 17:52:35 +03:00
blkdev_issue_flush ( journal - > j_fs_dev ) ;
2012-03-14 06:22:54 +04:00
2015-06-15 21:36:01 +03:00
return __jbd2_update_log_tail ( journal , first_tid , blocknr ) ;
2006-10-11 12:20:57 +04:00
}
/* Checkpoint list management */
/*
* journal_clean_one_cp_list
*
2011-06-13 23:38:22 +04:00
* Find all the written - back checkpoint buffers in the given list and
2015-07-28 21:57:14 +03:00
* release them . If ' destroy ' is set , clean all buffers unconditionally .
2006-10-11 12:20:57 +04:00
*
* Called with j_list_lock held .
2014-09-18 08:58:12 +04:00
* Returns 1 if we freed the transaction , 0 otherwise .
2006-10-11 12:20:57 +04:00
*/
2015-07-28 21:57:14 +03:00
static int journal_clean_one_cp_list ( struct journal_head * jh , bool destroy )
2006-10-11 12:20:57 +04:00
{
struct journal_head * last_jh ;
struct journal_head * next_jh = jh ;
2014-09-18 08:58:12 +04:00
int ret ;
2006-10-11 12:20:57 +04:00
if ( ! jh )
return 0 ;
last_jh = jh - > b_cpprev ;
do {
jh = next_jh ;
next_jh = jh - > b_cpnext ;
2015-07-28 21:57:14 +03:00
if ( ! destroy )
ret = __try_to_free_cp_buf ( jh ) ;
else
ret = __jbd2_journal_remove_checkpoint ( jh ) + 1 ;
2014-09-18 08:42:16 +04:00
if ( ! ret )
2015-10-18 05:35:09 +03:00
return 0 ;
2014-09-18 08:58:12 +04:00
if ( ret = = 2 )
return 1 ;
2006-10-11 12:20:57 +04:00
/*
* This function only frees up some memory
* if possible so we dont have an obligation
* to finish processing . Bail out if preemption
* requested :
*/
if ( need_resched ( ) )
2015-10-18 05:35:09 +03:00
return 0 ;
2006-10-11 12:20:57 +04:00
} while ( jh ! = last_jh ) ;
2015-10-18 05:35:09 +03:00
return 0 ;
2006-10-11 12:20:57 +04:00
}
/*
* journal_clean_checkpoint_list
*
* Find all the written - back checkpoint buffers in the journal and release them .
2015-07-28 21:57:14 +03:00
* If ' destroy ' is set , release all buffers unconditionally .
2006-10-11 12:20:57 +04:00
*
* Called with j_list_lock held .
*/
2015-07-28 21:57:14 +03:00
void __jbd2_journal_clean_checkpoint_list ( journal_t * journal , bool destroy )
2006-10-11 12:20:57 +04:00
{
transaction_t * transaction , * last_transaction , * next_transaction ;
2014-09-18 08:42:16 +04:00
int ret ;
2006-10-11 12:20:57 +04:00
transaction = journal - > j_checkpoint_transactions ;
if ( ! transaction )
2014-09-18 08:58:12 +04:00
return ;
2006-10-11 12:20:57 +04:00
last_transaction = transaction - > t_cpprev ;
next_transaction = transaction ;
do {
transaction = next_transaction ;
next_transaction = transaction - > t_cpnext ;
2015-07-28 21:57:14 +03:00
ret = journal_clean_one_cp_list ( transaction - > t_checkpoint_list ,
destroy ) ;
2006-10-11 12:20:57 +04:00
/*
* This function only frees up some memory if possible so we
* dont have an obligation to finish processing . Bail out if
* preemption requested :
*/
2014-09-18 08:58:12 +04:00
if ( need_resched ( ) )
return ;
if ( ret )
2006-10-11 12:20:57 +04:00
continue ;
/*
* It is essential that we are as careful as in the case of
* t_checkpoint_list with removing the buffer from the list as
* we can possibly see not yet submitted buffers on io_list
*/
2014-09-18 08:58:12 +04:00
ret = journal_clean_one_cp_list ( transaction - >
2015-07-28 21:57:14 +03:00
t_checkpoint_io_list , destroy ) ;
2014-09-18 08:58:12 +04:00
if ( need_resched ( ) )
return ;
/*
* Stop scanning if we couldn ' t free the transaction . This
* avoids pointless scanning of transactions which still
* weren ' t checkpointed .
*/
if ( ! ret )
return ;
2006-10-11 12:20:57 +04:00
} while ( transaction ! = last_transaction ) ;
}
2015-07-28 21:57:14 +03:00
/*
* Remove buffers from all checkpoint lists as journal is aborted and we just
* need to free memory
*/
void jbd2_journal_destroy_checkpoint ( journal_t * journal )
{
/*
* We loop because __jbd2_journal_clean_checkpoint_list ( ) may abort
* early due to a need of rescheduling .
*/
while ( 1 ) {
spin_lock ( & journal - > j_list_lock ) ;
if ( ! journal - > j_checkpoint_transactions ) {
spin_unlock ( & journal - > j_list_lock ) ;
break ;
}
__jbd2_journal_clean_checkpoint_list ( journal , true ) ;
spin_unlock ( & journal - > j_list_lock ) ;
cond_resched ( ) ;
}
}
2006-10-11 12:20:57 +04:00
/*
* journal_remove_checkpoint : called after a buffer has been committed
* to disk ( either by being write - back flushed to disk , or being
* committed to the log ) .
*
* We cannot safely clean a transaction out of the log until all of the
* buffer updates committed in that transaction have safely been stored
* elsewhere on disk . To achieve this , all of the buffers in a
* transaction need to be maintained on the transaction ' s checkpoint
* lists until they have been rewritten , at which point this function is
* called to remove the buffer from the existing transaction ' s
* checkpoint lists .
*
* The function returns 1 if it frees the transaction , 0 otherwise .
2011-06-13 23:38:22 +04:00
* The function can free jh and bh .
2006-10-11 12:20:57 +04:00
*
* This function is called with j_list_lock held .
*/
2006-10-11 12:20:59 +04:00
int __jbd2_journal_remove_checkpoint ( struct journal_head * jh )
2006-10-11 12:20:57 +04:00
{
2009-09-30 08:32:06 +04:00
struct transaction_chp_stats_s * stats ;
2006-10-11 12:20:57 +04:00
transaction_t * transaction ;
journal_t * journal ;
int ret = 0 ;
JBUFFER_TRACE ( jh , " entry " ) ;
if ( ( transaction = jh - > b_cp_transaction ) = = NULL ) {
JBUFFER_TRACE ( jh , " not on transaction " ) ;
goto out ;
}
journal = transaction - > t_journal ;
2011-06-13 23:38:22 +04:00
JBUFFER_TRACE ( jh , " removing from transaction " ) ;
2006-10-11 12:20:57 +04:00
__buffer_unlink ( jh ) ;
jh - > b_cp_transaction = NULL ;
2011-06-13 23:38:22 +04:00
jbd2_journal_put_journal_head ( jh ) ;
2006-10-11 12:20:57 +04:00
if ( transaction - > t_checkpoint_list ! = NULL | |
transaction - > t_checkpoint_io_list ! = NULL )
goto out ;
/*
* There is one special case to worry about : if we have just pulled the
2008-01-29 07:58:27 +03:00
* buffer off a running or committing transaction ' s checkpoing list ,
* then even if the checkpoint list is empty , the transaction obviously
* cannot be dropped !
2006-10-11 12:20:57 +04:00
*
2008-01-29 07:58:27 +03:00
* The locking here around t_state is a bit sleazy .
2006-10-11 12:20:59 +04:00
* See the comment at the end of jbd2_journal_commit_transaction ( ) .
2006-10-11 12:20:57 +04:00
*/
2011-06-13 23:38:22 +04:00
if ( transaction - > t_state ! = T_FINISHED )
2006-10-11 12:20:57 +04:00
goto out ;
/* OK, that was the last buffer for the transaction: we can now
safely remove this transaction from the log */
2009-09-30 08:32:06 +04:00
stats = & transaction - > t_chp_stats ;
if ( stats - > cs_chp_time )
stats - > cs_chp_time = jbd2_time_diff ( stats - > cs_chp_time ,
jiffies ) ;
trace_jbd2_checkpoint_stats ( journal - > j_fs_dev - > bd_dev ,
transaction - > t_tid , stats ) ;
2006-10-11 12:20:57 +04:00
2006-10-11 12:20:59 +04:00
__jbd2_journal_drop_transaction ( journal , transaction ) ;
2012-02-21 02:53:02 +04:00
jbd2_journal_free_transaction ( transaction ) ;
2006-10-11 12:20:57 +04:00
ret = 1 ;
out :
return ret ;
}
/*
* journal_insert_checkpoint : put a committed buffer onto a checkpoint
* list so that we know when it is safe to clean the transaction out of
* the log .
*
* Called with the journal locked .
* Called with j_list_lock held .
*/
2006-10-11 12:20:59 +04:00
void __jbd2_journal_insert_checkpoint ( struct journal_head * jh ,
2006-10-11 12:20:57 +04:00
transaction_t * transaction )
{
JBUFFER_TRACE ( jh , " entry " ) ;
J_ASSERT_JH ( jh , buffer_dirty ( jh2bh ( jh ) ) | | buffer_jbddirty ( jh2bh ( jh ) ) ) ;
J_ASSERT_JH ( jh , jh - > b_cp_transaction = = NULL ) ;
2011-06-13 23:38:22 +04:00
/* Get reference for checkpointing transaction */
jbd2_journal_grab_journal_head ( jh2bh ( jh ) ) ;
2006-10-11 12:20:57 +04:00
jh - > b_cp_transaction = transaction ;
if ( ! transaction - > t_checkpoint_list ) {
jh - > b_cpnext = jh - > b_cpprev = jh ;
} else {
jh - > b_cpnext = transaction - > t_checkpoint_list ;
jh - > b_cpprev = transaction - > t_checkpoint_list - > b_cpprev ;
jh - > b_cpprev - > b_cpnext = jh ;
jh - > b_cpnext - > b_cpprev = jh ;
}
transaction - > t_checkpoint_list = jh ;
}
/*
* We ' ve finished with this transaction structure : adios . . .
*
* The transaction must have no links except for the checkpoint by this
* point .
*
* Called with the journal locked .
* Called with j_list_lock held .
*/
2006-10-11 12:20:59 +04:00
void __jbd2_journal_drop_transaction ( journal_t * journal , transaction_t * transaction )
2006-10-11 12:20:57 +04:00
{
assert_spin_locked ( & journal - > j_list_lock ) ;
if ( transaction - > t_cpnext ) {
transaction - > t_cpnext - > t_cpprev = transaction - > t_cpprev ;
transaction - > t_cpprev - > t_cpnext = transaction - > t_cpnext ;
if ( journal - > j_checkpoint_transactions = = transaction )
journal - > j_checkpoint_transactions =
transaction - > t_cpnext ;
if ( journal - > j_checkpoint_transactions = = transaction )
journal - > j_checkpoint_transactions = NULL ;
}
J_ASSERT ( transaction - > t_state = = T_FINISHED ) ;
J_ASSERT ( transaction - > t_buffers = = NULL ) ;
J_ASSERT ( transaction - > t_forget = = NULL ) ;
J_ASSERT ( transaction - > t_shadow_list = = NULL ) ;
J_ASSERT ( transaction - > t_checkpoint_list = = NULL ) ;
J_ASSERT ( transaction - > t_checkpoint_io_list = = NULL ) ;
2010-08-02 16:43:25 +04:00
J_ASSERT ( atomic_read ( & transaction - > t_updates ) = = 0 ) ;
2006-10-11 12:20:57 +04:00
J_ASSERT ( journal - > j_committing_transaction ! = transaction ) ;
J_ASSERT ( journal - > j_running_transaction ! = transaction ) ;
2012-02-21 02:53:01 +04:00
trace_jbd2_drop_transaction ( journal , transaction ) ;
2006-10-11 12:20:57 +04:00
jbd_debug ( 1 , " Dropping transaction %d, all done \n " , transaction - > t_tid ) ;
}