Skip to content

Commit 9dbc1c0

Browse files
committed
Merge tag 'xfs-5.10-fixes-3' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs fixes from Darrick Wong: - Fix an uninitialized struct problem - Fix an iomap problem zeroing unwritten EOF blocks - Fix some clumsy error handling when writeback fails on filesystems with blocksize < pagesize - Fix a retry loop not resetting loop variables properly - Fix scrub flagging rtinherit inodes on a non-rt fs, since the kernel actually does permit that combination - Fix excessive page cache flushing when unsharing part of a file * tag 'xfs-5.10-fixes-3' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: only flush the unshared range in xfs_reflink_unshare xfs: fix scrub flagging rtinherit even if there is no rt device xfs: fix missing CoW blocks writeback conversion retry iomap: clean up writeback state logic on writepage error iomap: support partial page discard on writeback block mapping failure xfs: flush new eof page on truncate to avoid post-eof corruption xfs: set xefi_discard when creating a deferred agfl free log intent item
2 parents 6b2c4d5 + 46afb06 commit 9dbc1c0

File tree

8 files changed

+38
-33
lines changed

8 files changed

+38
-33
lines changed

fs/iomap/buffered-io.c

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,7 @@ iomap_writepage_map(struct iomap_writepage_ctx *wpc,
13741374
WARN_ON_ONCE(!wpc->ioend && !list_empty(&submit_list));
13751375
WARN_ON_ONCE(!PageLocked(page));
13761376
WARN_ON_ONCE(PageWriteback(page));
1377+
WARN_ON_ONCE(PageDirty(page));
13771378

13781379
/*
13791380
* We cannot cancel the ioend directly here on error. We may have
@@ -1382,33 +1383,22 @@ iomap_writepage_map(struct iomap_writepage_ctx *wpc,
13821383
* appropriately.
13831384
*/
13841385
if (unlikely(error)) {
1386+
/*
1387+
* Let the filesystem know what portion of the current page
1388+
* failed to map. If the page wasn't been added to ioend, it
1389+
* won't be affected by I/O completion and we must unlock it
1390+
* now.
1391+
*/
1392+
if (wpc->ops->discard_page)
1393+
wpc->ops->discard_page(page, file_offset);
13851394
if (!count) {
1386-
/*
1387-
* If the current page hasn't been added to ioend, it
1388-
* won't be affected by I/O completions and we must
1389-
* discard and unlock it right here.
1390-
*/
1391-
if (wpc->ops->discard_page)
1392-
wpc->ops->discard_page(page);
13931395
ClearPageUptodate(page);
13941396
unlock_page(page);
13951397
goto done;
13961398
}
1397-
1398-
/*
1399-
* If the page was not fully cleaned, we need to ensure that the
1400-
* higher layers come back to it correctly. That means we need
1401-
* to keep the page dirty, and for WB_SYNC_ALL writeback we need
1402-
* to ensure the PAGECACHE_TAG_TOWRITE index mark is not removed
1403-
* so another attempt to write this page in this writeback sweep
1404-
* will be made.
1405-
*/
1406-
set_page_writeback_keepwrite(page);
1407-
} else {
1408-
clear_page_dirty_for_io(page);
1409-
set_page_writeback(page);
14101399
}
14111400

1401+
set_page_writeback(page);
14121402
unlock_page(page);
14131403

14141404
/*

fs/xfs/libxfs/xfs_alloc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2467,6 +2467,7 @@ xfs_defer_agfl_block(
24672467
new->xefi_startblock = XFS_AGB_TO_FSB(mp, agno, agbno);
24682468
new->xefi_blockcount = 1;
24692469
new->xefi_oinfo = *oinfo;
2470+
new->xefi_skip_discard = false;
24702471

24712472
trace_xfs_agfl_free_defer(mp, agno, 0, agbno, 1);
24722473

fs/xfs/libxfs/xfs_bmap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ struct xfs_extent_free_item
5252
{
5353
xfs_fsblock_t xefi_startblock;/* starting fs block number */
5454
xfs_extlen_t xefi_blockcount;/* number of blocks in extent */
55+
bool xefi_skip_discard;
5556
struct list_head xefi_list;
5657
struct xfs_owner_info xefi_oinfo; /* extent owner */
57-
bool xefi_skip_discard;
5858
};
5959

6060
#define XFS_BMAP_MAX_NMAP 4

fs/xfs/scrub/inode.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,7 @@ xchk_inode_flags(
121121
goto bad;
122122

123123
/* rt flags require rt device */
124-
if ((flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT)) &&
125-
!mp->m_rtdev_targp)
124+
if ((flags & XFS_DIFLAG_REALTIME) && !mp->m_rtdev_targp)
126125
goto bad;
127126

128127
/* new rt bitmap flag only valid for rbmino */

fs/xfs/xfs_aops.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,8 @@ xfs_map_blocks(
346346
ssize_t count = i_blocksize(inode);
347347
xfs_fileoff_t offset_fsb = XFS_B_TO_FSBT(mp, offset);
348348
xfs_fileoff_t end_fsb = XFS_B_TO_FSB(mp, offset + count);
349-
xfs_fileoff_t cow_fsb = NULLFILEOFF;
350-
int whichfork = XFS_DATA_FORK;
349+
xfs_fileoff_t cow_fsb;
350+
int whichfork;
351351
struct xfs_bmbt_irec imap;
352352
struct xfs_iext_cursor icur;
353353
int retries = 0;
@@ -381,6 +381,8 @@ xfs_map_blocks(
381381
* landed in a hole and we skip the block.
382382
*/
383383
retry:
384+
cow_fsb = NULLFILEOFF;
385+
whichfork = XFS_DATA_FORK;
384386
xfs_ilock(ip, XFS_ILOCK_SHARED);
385387
ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_BTREE ||
386388
(ip->i_df.if_flags & XFS_IFEXTENTS));
@@ -527,28 +529,30 @@ xfs_prepare_ioend(
527529
*/
528530
static void
529531
xfs_discard_page(
530-
struct page *page)
532+
struct page *page,
533+
loff_t fileoff)
531534
{
532535
struct inode *inode = page->mapping->host;
533536
struct xfs_inode *ip = XFS_I(inode);
534537
struct xfs_mount *mp = ip->i_mount;
535-
loff_t offset = page_offset(page);
536-
xfs_fileoff_t start_fsb = XFS_B_TO_FSBT(mp, offset);
538+
unsigned int pageoff = offset_in_page(fileoff);
539+
xfs_fileoff_t start_fsb = XFS_B_TO_FSBT(mp, fileoff);
540+
xfs_fileoff_t pageoff_fsb = XFS_B_TO_FSBT(mp, pageoff);
537541
int error;
538542

539543
if (XFS_FORCED_SHUTDOWN(mp))
540544
goto out_invalidate;
541545

542546
xfs_alert_ratelimited(mp,
543547
"page discard on page "PTR_FMT", inode 0x%llx, offset %llu.",
544-
page, ip->i_ino, offset);
548+
page, ip->i_ino, fileoff);
545549

546550
error = xfs_bmap_punch_delalloc_range(ip, start_fsb,
547-
i_blocks_per_page(inode, page));
551+
i_blocks_per_page(inode, page) - pageoff_fsb);
548552
if (error && !XFS_FORCED_SHUTDOWN(mp))
549553
xfs_alert(mp, "page discard unable to remove delalloc mapping.");
550554
out_invalidate:
551-
iomap_invalidatepage(page, 0, PAGE_SIZE);
555+
iomap_invalidatepage(page, pageoff, PAGE_SIZE - pageoff);
552556
}
553557

554558
static const struct iomap_writeback_ops xfs_writeback_ops = {

fs/xfs/xfs_iops.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,16 @@ xfs_setattr_size(
911911
error = iomap_zero_range(inode, oldsize, newsize - oldsize,
912912
&did_zeroing, &xfs_buffered_write_iomap_ops);
913913
} else {
914+
/*
915+
* iomap won't detect a dirty page over an unwritten block (or a
916+
* cow block over a hole) and subsequently skips zeroing the
917+
* newly post-EOF portion of the page. Flush the new EOF to
918+
* convert the block before the pagecache truncate.
919+
*/
920+
error = filemap_write_and_wait_range(inode->i_mapping, newsize,
921+
newsize);
922+
if (error)
923+
return error;
914924
error = iomap_truncate_page(inode, newsize, &did_zeroing,
915925
&xfs_buffered_write_iomap_ops);
916926
}

fs/xfs/xfs_reflink.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1502,7 +1502,8 @@ xfs_reflink_unshare(
15021502
&xfs_buffered_write_iomap_ops);
15031503
if (error)
15041504
goto out;
1505-
error = filemap_write_and_wait(inode->i_mapping);
1505+
1506+
error = filemap_write_and_wait_range(inode->i_mapping, offset, len);
15061507
if (error)
15071508
goto out;
15081509

include/linux/iomap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ struct iomap_writeback_ops {
221221
* Optional, allows the file system to discard state on a page where
222222
* we failed to submit any I/O.
223223
*/
224-
void (*discard_page)(struct page *page);
224+
void (*discard_page)(struct page *page, loff_t fileoff);
225225
};
226226

227227
struct iomap_writepage_ctx {

0 commit comments

Comments
 (0)