ocfs2: fix trans extend while flush truncate log
Every time, ocfs2_extend_trans() included a credit for truncate log inode, but as that inode had been managed by jbd2 running transaction first time, it will not consume that credit until jbd2_journal_restart(). Since total credits to extend always included the un-consumed ones, there will be more and more un-consumed credit, at last jbd2_journal_restart() will fail due to credit number over the half of max transction credit. The following error was caught when unlinking a large file with many extents: ------------[ cut here ]------------ WARNING: CPU: 0 PID: 13626 at fs/jbd2/transaction.c:269 start_this_handle+0x4c3/0x510 [jbd2]() Modules linked in: ocfs2 nfsd lockd grace nfs_acl auth_rpcgss sunrpc autofs4 ocfs2_dlmfs ocfs2_stack_o2cb ocfs2_dlm ocfs2_nodemanager ocfs2_stackglue configfs sd_mod sg ip6t_REJECT nf_reject_ipv6 nf_conntrack_ipv6 nf_defrag_ipv6 xt_state nf_conntrack ip6table_filter ip6_tables be2iscsi iscsi_boot_sysfs bnx2i cnic uio cxgb4i cxgb4 cxgb3i libcxgbi cxgb3 mdio ib_iser rdma_cm ib_cm iw_cm ib_sa ib_mad ib_core ib_addr ipv6 iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi ppdev xen_kbdfront xen_netfront fb_sys_fops sysimgblt sysfillrect syscopyarea parport_pc parport pcspkr i2c_piix4 i2c_core acpi_cpufreq ext4 jbd2 mbcache xen_blkfront floppy pata_acpi ata_generic ata_piix dm_mirror dm_region_hash dm_log dm_mod CPU: 0 PID: 13626 Comm: unlink Tainted: G W 4.1.12-37.6.3.el6uek.x86_64 #2 Hardware name: Xen HVM domU, BIOS 4.4.4OVM 02/11/2016 Call Trace: dump_stack+0x48/0x5c warn_slowpath_common+0x95/0xe0 warn_slowpath_null+0x1a/0x20 start_this_handle+0x4c3/0x510 [jbd2] jbd2__journal_restart+0x161/0x1b0 [jbd2] jbd2_journal_restart+0x13/0x20 [jbd2] ocfs2_extend_trans+0x74/0x220 [ocfs2] ocfs2_replay_truncate_records+0x93/0x360 [ocfs2] __ocfs2_flush_truncate_log+0x13e/0x3a0 [ocfs2] ocfs2_remove_btree_range+0x458/0x7f0 [ocfs2] ocfs2_commit_truncate+0x1b3/0x6f0 [ocfs2] ocfs2_truncate_for_delete+0xbd/0x380 [ocfs2] ocfs2_wipe_inode+0x136/0x6a0 [ocfs2] ocfs2_delete_inode+0x2a2/0x3e0 [ocfs2] ocfs2_evict_inode+0x28/0x60 [ocfs2] evict+0xab/0x1a0 iput_final+0xf6/0x190 iput+0xc8/0xe0 do_unlinkat+0x1b7/0x310 SyS_unlink+0x16/0x20 system_call_fastpath+0x12/0x71 ---[ end trace 28aa7410e69369cf ]--- JBD2: unlink wants too many credits (251 > 128) Link: http://lkml.kernel.org/r/1473674623-11810-1-git-send-email-junxiao.bi@oracle.com Signed-off-by: Junxiao Bi <junxiao.bi@oracle.com> Reviewed-by: Joseph Qi <joseph.qi@huawei.com> Cc: Mark Fasheh <mfasheh@suse.de> Cc: Joel Becker <jlbec@evilplan.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
31b4beb473
commit
2b0ad0085a
|
@ -5922,7 +5922,6 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb,
|
|||
}
|
||||
|
||||
static int ocfs2_replay_truncate_records(struct ocfs2_super *osb,
|
||||
handle_t *handle,
|
||||
struct inode *data_alloc_inode,
|
||||
struct buffer_head *data_alloc_bh)
|
||||
{
|
||||
|
@ -5935,11 +5934,19 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb,
|
|||
struct ocfs2_truncate_log *tl;
|
||||
struct inode *tl_inode = osb->osb_tl_inode;
|
||||
struct buffer_head *tl_bh = osb->osb_tl_bh;
|
||||
handle_t *handle;
|
||||
|
||||
di = (struct ocfs2_dinode *) tl_bh->b_data;
|
||||
tl = &di->id2.i_dealloc;
|
||||
i = le16_to_cpu(tl->tl_used) - 1;
|
||||
while (i >= 0) {
|
||||
handle = ocfs2_start_trans(osb, OCFS2_TRUNCATE_LOG_FLUSH_ONE_REC);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Caller has given us at least enough credits to
|
||||
* update the truncate log dinode */
|
||||
status = ocfs2_journal_access_di(handle, INODE_CACHE(tl_inode), tl_bh,
|
||||
|
@ -5974,12 +5981,7 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb,
|
|||
}
|
||||
}
|
||||
|
||||
status = ocfs2_extend_trans(handle,
|
||||
OCFS2_TRUNCATE_LOG_FLUSH_ONE_REC);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
i--;
|
||||
}
|
||||
|
||||
|
@ -5994,7 +5996,6 @@ int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
|
|||
{
|
||||
int status;
|
||||
unsigned int num_to_flush;
|
||||
handle_t *handle;
|
||||
struct inode *tl_inode = osb->osb_tl_inode;
|
||||
struct inode *data_alloc_inode = NULL;
|
||||
struct buffer_head *tl_bh = osb->osb_tl_bh;
|
||||
|
@ -6038,21 +6039,11 @@ int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
|
|||
goto out_mutex;
|
||||
}
|
||||
|
||||
handle = ocfs2_start_trans(osb, OCFS2_TRUNCATE_LOG_FLUSH_ONE_REC);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
mlog_errno(status);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
status = ocfs2_replay_truncate_records(osb, handle, data_alloc_inode,
|
||||
status = ocfs2_replay_truncate_records(osb, data_alloc_inode,
|
||||
data_alloc_bh);
|
||||
if (status < 0)
|
||||
mlog_errno(status);
|
||||
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
|
||||
out_unlock:
|
||||
brelse(data_alloc_bh);
|
||||
ocfs2_inode_unlock(data_alloc_inode, 1);
|
||||
|
||||
|
|
Loading…
Reference in New Issue