FAILED: patch "[PATCH] gfs2: Never call gfs2_block_zero_range with an open" failed to apply to 5.4-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 70499cdfeb3625c87eebe4f7a7ea06fa7447e5df Mon Sep 17 00:00:00 2001
From: Bob Peterson <[email protected]>
Date: Fri, 24 Jul 2020 12:06:31 -0500
Subject: [PATCH] gfs2: Never call gfs2_block_zero_range with an open
transaction
Before this patch, some functions started transactions then they called gfs2_block_zero_range. However, gfs2_block_zero_range, like writes, can start transactions, which results in a recursive transaction error. For example:
do_shrink
trunc_start
gfs2_trans_begin <------------------------------------------------
gfs2_block_zero_range
iomap_zero_range(inode, from, length, NULL, &gfs2_iomap_ops);
iomap_apply ... iomap_zero_range_actor
iomap_begin
gfs2_iomap_begin
gfs2_iomap_begin_write
actor (iomap_zero_range_actor)
iomap_zero
iomap_write_begin
gfs2_iomap_page_prepare
gfs2_trans_begin <------------------------This patch reorders the callers of gfs2_block_zero_range so that they only start their transactions after the call. It also adds a BUG_ON to ensure this doesn't happen again.
fs/gfs2/bmap.c +39 -30
@@ -1351,9 +1351,15 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsireturn ret; } +/* +* NOTE: Never call gfs2_block_zero_range with an open transaction because it +* uses iomap write to perform its actions, which begin their own transactions +* (iomap_begin, page_prepare, etc.) +*/ static int gfs2_block_zero_range (struct inode *inode,loff_t from,unsigned int length) { +BUG_ON (current->journal_info);return iomap_zero_range (inode, from, length,NULL , &gfs2_iomap_ops); }
@@ -1414,6 +1420,16 @@ static int trunc_start(struct inode *inode, u64 newsize)u64 oldsize = inode->i_size;int error; +if (!gfs2_is_stuffed (ip)) { +unsigned int blocksize =i_blocksize (inode); +unsigned int offs = newsize & (blocksize -1 ); +if (offs) { + error =gfs2_block_zero_range (inode, newsize, + blocksize - offs); +if (error) +return error; + } + }if (journaled) error =gfs2_trans_begin (sdp,RES_DINODE +RES_JDATA ,GFS2_JTRUNC_REVOKES );else
@@ -1427,19 +1443,10 @@ static int trunc_start(struct inode *inode, u64 newsize)gfs2_trans_add_meta (ip->i_gl, dibh); -if (gfs2_is_stuffed (ip)) { +if (gfs2_is_stuffed (ip))gfs2_buffer_clear_tail (dibh,sizeof (struct gfs2_dinode ) + newsize); - }else { -unsigned int blocksize =i_blocksize (inode); -unsigned int offs = newsize & (blocksize -1 ); -if (offs) { - error =gfs2_block_zero_range (inode, newsize, - blocksize - offs); -if (error) - goto out; - } +else ip->i_diskflags |=GFS2_DIF_TRUNC_IN_PROG ; - }i_size_write (inode, newsize); ip->i_inode.i_mtime = ip->i_inode.i_ctime =current_time (&ip->i_inode);
@@ -2448,25 +2455,7 @@ int __gfs2_punch_hole(struct file *file, loff_t offset, loff_t length)loff_t start, end;int error; - start =round_down (offset, blocksize); - end =round_up (offset + length, blocksize) -1 ; - error =filemap_write_and_wait_range (inode->i_mapping, start, end); -if (error) -return error; - -if (gfs2_is_jdata (ip)) - error =gfs2_trans_begin (sdp,RES_DINODE +2 *RES_JDATA , -GFS2_JTRUNC_REVOKES ); -else - error =gfs2_trans_begin (sdp,RES_DINODE ,0 ); -if (error) -return error; - -if (gfs2_is_stuffed (ip)) { - error =stuffed_zero_range (inode, offset, length); -if (error) - goto out; - }else { +if (!gfs2_is_stuffed (ip)) {unsigned int start_off, end_len; start_off = offset & (blocksize -1 );
@@ -2489,6 +2478,26 @@ int __gfs2_punch_hole(struct file *file, loff_t offset, loff_t length) } } + start =round_down (offset, blocksize); + end =round_up (offset + length, blocksize) -1 ; + error =filemap_write_and_wait_range (inode->i_mapping, start, end); +if (error) +return error; + +if (gfs2_is_jdata (ip)) + error =gfs2_trans_begin (sdp,RES_DINODE +2 *RES_JDATA , +GFS2_JTRUNC_REVOKES ); +else + error =gfs2_trans_begin (sdp,RES_DINODE ,0 ); +if (error) +return error; + +if (gfs2_is_stuffed (ip)) { + error =stuffed_zero_range (inode, offset, length); +if (error) + goto out; + } +if (gfs2_is_jdata (ip)) {BUG_ON (!current->journal_info);gfs2_journaled_truncate_range (inode, offset, length);