2018-06-06 10:42:14 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
2005-11-02 11:58:39 +08:00
|
|
|
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
|
|
|
|
* All Rights Reserved.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
#include "xfs.h"
|
2013-10-23 07:36:05 +08:00
|
|
|
#include "xfs_shared.h"
|
2013-10-23 07:50:10 +08:00
|
|
|
#include "xfs_format.h"
|
|
|
|
#include "xfs_log_format.h"
|
|
|
|
#include "xfs_trans_resv.h"
|
2005-04-17 06:20:36 +08:00
|
|
|
#include "xfs_mount.h"
|
|
|
|
#include "xfs_inode.h"
|
2013-10-23 07:50:10 +08:00
|
|
|
#include "xfs_trans.h"
|
2012-03-13 16:41:05 +08:00
|
|
|
#include "xfs_inode_item.h"
|
2005-11-02 11:38:42 +08:00
|
|
|
#include "xfs_alloc.h"
|
2005-04-17 06:20:36 +08:00
|
|
|
#include "xfs_error.h"
|
|
|
|
#include "xfs_iomap.h"
|
2009-12-15 07:14:59 +08:00
|
|
|
#include "xfs_trace.h"
|
2010-03-05 10:00:42 +08:00
|
|
|
#include "xfs_bmap.h"
|
2013-08-12 18:49:42 +08:00
|
|
|
#include "xfs_bmap_util.h"
|
2013-10-23 07:51:50 +08:00
|
|
|
#include "xfs_bmap_btree.h"
|
2016-10-04 00:11:34 +08:00
|
|
|
#include "xfs_reflink.h"
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/writeback.h>
|
|
|
|
|
2016-02-15 14:21:19 +08:00
|
|
|
/*
|
|
|
|
* structure owned by writepages passed to individual writepage calls
|
|
|
|
*/
|
|
|
|
struct xfs_writepage_ctx {
|
|
|
|
struct xfs_bmbt_irec imap;
|
|
|
|
unsigned int io_type;
|
|
|
|
struct xfs_ioend *ioend;
|
|
|
|
};
|
|
|
|
|
2016-02-27 07:19:52 +08:00
|
|
|
struct block_device *
|
2007-09-14 13:23:17 +08:00
|
|
|
xfs_find_bdev_for_inode(
|
2010-04-28 20:28:52 +08:00
|
|
|
struct inode *inode)
|
2007-09-14 13:23:17 +08:00
|
|
|
{
|
2010-04-28 20:28:52 +08:00
|
|
|
struct xfs_inode *ip = XFS_I(inode);
|
2007-09-14 13:23:17 +08:00
|
|
|
struct xfs_mount *mp = ip->i_mount;
|
|
|
|
|
2007-11-23 13:29:42 +08:00
|
|
|
if (XFS_IS_REALTIME_INODE(ip))
|
2007-09-14 13:23:17 +08:00
|
|
|
return mp->m_rtdev_targp->bt_bdev;
|
|
|
|
else
|
|
|
|
return mp->m_ddev_targp->bt_bdev;
|
|
|
|
}
|
|
|
|
|
2017-08-25 06:12:50 +08:00
|
|
|
struct dax_device *
|
|
|
|
xfs_find_daxdev_for_inode(
|
|
|
|
struct inode *inode)
|
|
|
|
{
|
|
|
|
struct xfs_inode *ip = XFS_I(inode);
|
|
|
|
struct xfs_mount *mp = ip->i_mount;
|
|
|
|
|
|
|
|
if (XFS_IS_REALTIME_INODE(ip))
|
|
|
|
return mp->m_rtdev_targp->bt_daxdev;
|
|
|
|
else
|
|
|
|
return mp->m_ddev_targp->bt_daxdev;
|
|
|
|
}
|
|
|
|
|
2018-07-12 13:26:04 +08:00
|
|
|
static void
|
|
|
|
xfs_finish_page_writeback(
|
|
|
|
struct inode *inode,
|
|
|
|
struct bio_vec *bvec,
|
|
|
|
int error)
|
|
|
|
{
|
2018-07-12 13:26:05 +08:00
|
|
|
struct iomap_page *iop = to_iomap_page(bvec->bv_page);
|
|
|
|
|
2018-07-12 13:26:04 +08:00
|
|
|
if (error) {
|
|
|
|
SetPageError(bvec->bv_page);
|
|
|
|
mapping_set_error(inode->i_mapping, -EIO);
|
|
|
|
}
|
|
|
|
|
2018-07-12 13:26:05 +08:00
|
|
|
ASSERT(iop || i_blocksize(inode) == PAGE_SIZE);
|
|
|
|
ASSERT(!iop || atomic_read(&iop->write_count) > 0);
|
2017-09-03 00:53:41 +08:00
|
|
|
|
2018-07-12 13:26:05 +08:00
|
|
|
if (!iop || atomic_dec_and_test(&iop->write_count))
|
2017-09-03 00:53:41 +08:00
|
|
|
end_page_writeback(bvec->bv_page);
|
2016-04-06 06:12:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We're now finished for good with this ioend structure. Update the page
|
|
|
|
* state, release holds on bios, and finally free up memory. Do not use the
|
|
|
|
* ioend after this.
|
2006-01-11 12:40:13 +08:00
|
|
|
*/
|
2005-09-02 14:58:49 +08:00
|
|
|
STATIC void
|
|
|
|
xfs_destroy_ioend(
|
2016-04-06 06:34:30 +08:00
|
|
|
struct xfs_ioend *ioend,
|
|
|
|
int error)
|
2005-09-02 14:58:49 +08:00
|
|
|
{
|
2016-04-06 06:12:28 +08:00
|
|
|
struct inode *inode = ioend->io_inode;
|
2017-09-03 00:53:41 +08:00
|
|
|
struct bio *bio = &ioend->io_inline_bio;
|
|
|
|
struct bio *last = ioend->io_bio, *next;
|
|
|
|
u64 start = bio->bi_iter.bi_sector;
|
|
|
|
bool quiet = bio_flagged(bio, BIO_QUIET);
|
2006-01-11 12:40:13 +08:00
|
|
|
|
2016-04-06 06:34:30 +08:00
|
|
|
for (bio = &ioend->io_inline_bio; bio; bio = next) {
|
2016-04-06 06:12:28 +08:00
|
|
|
struct bio_vec *bvec;
|
|
|
|
int i;
|
|
|
|
|
2016-04-06 06:34:30 +08:00
|
|
|
/*
|
|
|
|
* For the last bio, bi_private points to the ioend, so we
|
|
|
|
* need to explicitly end the iteration here.
|
|
|
|
*/
|
|
|
|
if (bio == last)
|
|
|
|
next = NULL;
|
|
|
|
else
|
|
|
|
next = bio->bi_private;
|
2008-12-03 19:20:38 +08:00
|
|
|
|
2016-04-06 06:12:28 +08:00
|
|
|
/* walk each page on bio, ending page IO on them */
|
2018-07-12 13:26:05 +08:00
|
|
|
bio_for_each_segment_all(bvec, bio, i)
|
|
|
|
xfs_finish_page_writeback(inode, bvec, error);
|
2016-04-06 06:12:28 +08:00
|
|
|
bio_put(bio);
|
2006-01-11 12:40:13 +08:00
|
|
|
}
|
2017-09-03 00:53:41 +08:00
|
|
|
|
|
|
|
if (unlikely(error && !quiet)) {
|
|
|
|
xfs_err_ratelimited(XFS_I(inode)->i_mount,
|
|
|
|
"writeback error on sector %llu", start);
|
|
|
|
}
|
2005-09-02 14:58:49 +08:00
|
|
|
}
|
|
|
|
|
2011-08-23 16:28:11 +08:00
|
|
|
/*
|
|
|
|
* Fast and loose check if this write could update the on-disk inode size.
|
|
|
|
*/
|
|
|
|
static inline bool xfs_ioend_is_append(struct xfs_ioend *ioend)
|
|
|
|
{
|
|
|
|
return ioend->io_offset + ioend->io_size >
|
|
|
|
XFS_I(ioend->io_inode)->i_d.di_size;
|
|
|
|
}
|
|
|
|
|
2012-03-13 16:41:05 +08:00
|
|
|
STATIC int
|
|
|
|
xfs_setfilesize_trans_alloc(
|
|
|
|
struct xfs_ioend *ioend)
|
|
|
|
{
|
|
|
|
struct xfs_mount *mp = XFS_I(ioend->io_inode)->i_mount;
|
|
|
|
struct xfs_trans *tp;
|
|
|
|
int error;
|
|
|
|
|
2018-03-07 09:07:22 +08:00
|
|
|
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0,
|
|
|
|
XFS_TRANS_NOFS, &tp);
|
2016-04-06 07:19:55 +08:00
|
|
|
if (error)
|
2012-03-13 16:41:05 +08:00
|
|
|
return error;
|
|
|
|
|
|
|
|
ioend->io_append_trans = tp;
|
|
|
|
|
2012-06-12 22:20:39 +08:00
|
|
|
/*
|
2012-11-28 10:01:00 +08:00
|
|
|
* We may pass freeze protection with a transaction. So tell lockdep
|
2012-06-12 22:20:39 +08:00
|
|
|
* we released it.
|
|
|
|
*/
|
2015-07-20 05:48:20 +08:00
|
|
|
__sb_writers_release(ioend->io_inode->i_sb, SB_FREEZE_FS);
|
2012-03-13 16:41:05 +08:00
|
|
|
/*
|
|
|
|
* We hand off the transaction to the completion thread now, so
|
|
|
|
* clear the flag here.
|
|
|
|
*/
|
2017-05-04 05:53:12 +08:00
|
|
|
current_restore_flags_nested(&tp->t_pflags, PF_MEMALLOC_NOFS);
|
2012-03-13 16:41:05 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
[XFS] Fix to prevent the notorious 'NULL files' problem after a crash.
The problem that has been addressed is that of synchronising updates of
the file size with writes that extend a file. Without the fix the update
of a file's size, as a result of a write beyond eof, is independent of
when the cached data is flushed to disk. Often the file size update would
be written to the filesystem log before the data is flushed to disk. When
a system crashes between these two events and the filesystem log is
replayed on mount the file's size will be set but since the contents never
made it to disk the file is full of holes. If some of the cached data was
flushed to disk then it may just be a section of the file at the end that
has holes.
There are existing fixes to help alleviate this problem, particularly in
the case where a file has been truncated, that force cached data to be
flushed to disk when the file is closed. If the system crashes while the
file(s) are still open then this flushing will never occur.
The fix that we have implemented is to introduce a second file size,
called the in-memory file size, that represents the current file size as
viewed by the user. The existing file size, called the on-disk file size,
is the one that get's written to the filesystem log and we only update it
when it is safe to do so. When we write to a file beyond eof we only
update the in- memory file size in the write operation. Later when the I/O
operation, that flushes the cached data to disk completes, an I/O
completion routine will update the on-disk file size. The on-disk file
size will be updated to the maximum offset of the I/O or to the value of
the in-memory file size if the I/O includes eof.
SGI-PV: 958522
SGI-Modid: xfs-linux-melb:xfs-kern:28322a
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Tim Shimmin <tes@sgi.com>
2007-05-08 11:49:46 +08:00
|
|
|
/*
|
2011-12-19 04:00:12 +08:00
|
|
|
* Update on-disk file size now that data has been written to disk.
|
[XFS] Fix to prevent the notorious 'NULL files' problem after a crash.
The problem that has been addressed is that of synchronising updates of
the file size with writes that extend a file. Without the fix the update
of a file's size, as a result of a write beyond eof, is independent of
when the cached data is flushed to disk. Often the file size update would
be written to the filesystem log before the data is flushed to disk. When
a system crashes between these two events and the filesystem log is
replayed on mount the file's size will be set but since the contents never
made it to disk the file is full of holes. If some of the cached data was
flushed to disk then it may just be a section of the file at the end that
has holes.
There are existing fixes to help alleviate this problem, particularly in
the case where a file has been truncated, that force cached data to be
flushed to disk when the file is closed. If the system crashes while the
file(s) are still open then this flushing will never occur.
The fix that we have implemented is to introduce a second file size,
called the in-memory file size, that represents the current file size as
viewed by the user. The existing file size, called the on-disk file size,
is the one that get's written to the filesystem log and we only update it
when it is safe to do so. When we write to a file beyond eof we only
update the in- memory file size in the write operation. Later when the I/O
operation, that flushes the cached data to disk completes, an I/O
completion routine will update the on-disk file size. The on-disk file
size will be updated to the maximum offset of the I/O or to the value of
the in-memory file size if the I/O includes eof.
SGI-PV: 958522
SGI-Modid: xfs-linux-melb:xfs-kern:28322a
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Tim Shimmin <tes@sgi.com>
2007-05-08 11:49:46 +08:00
|
|
|
*/
|
2012-03-13 16:41:05 +08:00
|
|
|
STATIC int
|
2016-09-19 09:26:41 +08:00
|
|
|
__xfs_setfilesize(
|
2015-02-02 07:02:09 +08:00
|
|
|
struct xfs_inode *ip,
|
|
|
|
struct xfs_trans *tp,
|
|
|
|
xfs_off_t offset,
|
|
|
|
size_t size)
|
[XFS] Fix to prevent the notorious 'NULL files' problem after a crash.
The problem that has been addressed is that of synchronising updates of
the file size with writes that extend a file. Without the fix the update
of a file's size, as a result of a write beyond eof, is independent of
when the cached data is flushed to disk. Often the file size update would
be written to the filesystem log before the data is flushed to disk. When
a system crashes between these two events and the filesystem log is
replayed on mount the file's size will be set but since the contents never
made it to disk the file is full of holes. If some of the cached data was
flushed to disk then it may just be a section of the file at the end that
has holes.
There are existing fixes to help alleviate this problem, particularly in
the case where a file has been truncated, that force cached data to be
flushed to disk when the file is closed. If the system crashes while the
file(s) are still open then this flushing will never occur.
The fix that we have implemented is to introduce a second file size,
called the in-memory file size, that represents the current file size as
viewed by the user. The existing file size, called the on-disk file size,
is the one that get's written to the filesystem log and we only update it
when it is safe to do so. When we write to a file beyond eof we only
update the in- memory file size in the write operation. Later when the I/O
operation, that flushes the cached data to disk completes, an I/O
completion routine will update the on-disk file size. The on-disk file
size will be updated to the maximum offset of the I/O or to the value of
the in-memory file size if the I/O includes eof.
SGI-PV: 958522
SGI-Modid: xfs-linux-melb:xfs-kern:28322a
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Tim Shimmin <tes@sgi.com>
2007-05-08 11:49:46 +08:00
|
|
|
{
|
|
|
|
xfs_fsize_t isize;
|
|
|
|
|
2012-02-29 17:53:48 +08:00
|
|
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
2015-02-02 07:02:09 +08:00
|
|
|
isize = xfs_new_eof(ip, offset + size);
|
2012-03-13 16:41:05 +08:00
|
|
|
if (!isize) {
|
|
|
|
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
2015-06-04 11:47:56 +08:00
|
|
|
xfs_trans_cancel(tp);
|
2012-03-13 16:41:05 +08:00
|
|
|
return 0;
|
[XFS] Fix to prevent the notorious 'NULL files' problem after a crash.
The problem that has been addressed is that of synchronising updates of
the file size with writes that extend a file. Without the fix the update
of a file's size, as a result of a write beyond eof, is independent of
when the cached data is flushed to disk. Often the file size update would
be written to the filesystem log before the data is flushed to disk. When
a system crashes between these two events and the filesystem log is
replayed on mount the file's size will be set but since the contents never
made it to disk the file is full of holes. If some of the cached data was
flushed to disk then it may just be a section of the file at the end that
has holes.
There are existing fixes to help alleviate this problem, particularly in
the case where a file has been truncated, that force cached data to be
flushed to disk when the file is closed. If the system crashes while the
file(s) are still open then this flushing will never occur.
The fix that we have implemented is to introduce a second file size,
called the in-memory file size, that represents the current file size as
viewed by the user. The existing file size, called the on-disk file size,
is the one that get's written to the filesystem log and we only update it
when it is safe to do so. When we write to a file beyond eof we only
update the in- memory file size in the write operation. Later when the I/O
operation, that flushes the cached data to disk completes, an I/O
completion routine will update the on-disk file size. The on-disk file
size will be updated to the maximum offset of the I/O or to the value of
the in-memory file size if the I/O includes eof.
SGI-PV: 958522
SGI-Modid: xfs-linux-melb:xfs-kern:28322a
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Tim Shimmin <tes@sgi.com>
2007-05-08 11:49:46 +08:00
|
|
|
}
|
|
|
|
|
2015-02-02 07:02:09 +08:00
|
|
|
trace_xfs_setfilesize(ip, offset, size);
|
2012-03-13 16:41:05 +08:00
|
|
|
|
|
|
|
ip->i_d.di_size = isize;
|
|
|
|
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
|
|
|
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
|
|
|
|
2015-06-04 11:48:08 +08:00
|
|
|
return xfs_trans_commit(tp);
|
2010-02-17 13:36:29 +08:00
|
|
|
}
|
|
|
|
|
2016-09-19 09:26:41 +08:00
|
|
|
int
|
|
|
|
xfs_setfilesize(
|
|
|
|
struct xfs_inode *ip,
|
|
|
|
xfs_off_t offset,
|
|
|
|
size_t size)
|
|
|
|
{
|
|
|
|
struct xfs_mount *mp = ip->i_mount;
|
|
|
|
struct xfs_trans *tp;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0, 0, &tp);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
|
|
|
|
return __xfs_setfilesize(ip, tp, offset, size);
|
|
|
|
}
|
|
|
|
|
2015-02-02 07:02:09 +08:00
|
|
|
STATIC int
|
|
|
|
xfs_setfilesize_ioend(
|
2016-04-06 06:34:30 +08:00
|
|
|
struct xfs_ioend *ioend,
|
|
|
|
int error)
|
2015-02-02 07:02:09 +08:00
|
|
|
{
|
|
|
|
struct xfs_inode *ip = XFS_I(ioend->io_inode);
|
|
|
|
struct xfs_trans *tp = ioend->io_append_trans;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The transaction may have been allocated in the I/O submission thread,
|
|
|
|
* thus we need to mark ourselves as being in a transaction manually.
|
|
|
|
* Similarly for freeze protection.
|
|
|
|
*/
|
2017-05-04 05:53:12 +08:00
|
|
|
current_set_flags_nested(&tp->t_pflags, PF_MEMALLOC_NOFS);
|
2015-07-20 05:48:20 +08:00
|
|
|
__sb_writers_acquired(VFS_I(ip)->i_sb, SB_FREEZE_FS);
|
2015-02-02 07:02:09 +08:00
|
|
|
|
2015-10-12 12:28:39 +08:00
|
|
|
/* we abort the update if there was an IO error */
|
2016-04-06 06:34:30 +08:00
|
|
|
if (error) {
|
2015-10-12 12:28:39 +08:00
|
|
|
xfs_trans_cancel(tp);
|
2016-04-06 06:34:30 +08:00
|
|
|
return error;
|
2015-10-12 12:28:39 +08:00
|
|
|
}
|
|
|
|
|
2016-09-19 09:26:41 +08:00
|
|
|
return __xfs_setfilesize(ip, tp, ioend->io_offset, ioend->io_size);
|
2015-02-02 07:02:09 +08:00
|
|
|
}
|
|
|
|
|
2005-09-02 14:58:49 +08:00
|
|
|
/*
|
2009-10-30 17:11:47 +08:00
|
|
|
* IO write completion.
|
2006-01-11 12:40:13 +08:00
|
|
|
*/
|
|
|
|
STATIC void
|
2009-10-30 17:11:47 +08:00
|
|
|
xfs_end_io(
|
2010-02-17 13:36:29 +08:00
|
|
|
struct work_struct *work)
|
2005-09-02 14:58:49 +08:00
|
|
|
{
|
2016-04-06 06:34:30 +08:00
|
|
|
struct xfs_ioend *ioend =
|
|
|
|
container_of(work, struct xfs_ioend, io_work);
|
|
|
|
struct xfs_inode *ip = XFS_I(ioend->io_inode);
|
2017-03-03 07:02:51 +08:00
|
|
|
xfs_off_t offset = ioend->io_offset;
|
|
|
|
size_t size = ioend->io_size;
|
2017-06-03 15:38:06 +08:00
|
|
|
int error;
|
[XFS] Fix to prevent the notorious 'NULL files' problem after a crash.
The problem that has been addressed is that of synchronising updates of
the file size with writes that extend a file. Without the fix the update
of a file's size, as a result of a write beyond eof, is independent of
when the cached data is flushed to disk. Often the file size update would
be written to the filesystem log before the data is flushed to disk. When
a system crashes between these two events and the filesystem log is
replayed on mount the file's size will be set but since the contents never
made it to disk the file is full of holes. If some of the cached data was
flushed to disk then it may just be a section of the file at the end that
has holes.
There are existing fixes to help alleviate this problem, particularly in
the case where a file has been truncated, that force cached data to be
flushed to disk when the file is closed. If the system crashes while the
file(s) are still open then this flushing will never occur.
The fix that we have implemented is to introduce a second file size,
called the in-memory file size, that represents the current file size as
viewed by the user. The existing file size, called the on-disk file size,
is the one that get's written to the filesystem log and we only update it
when it is safe to do so. When we write to a file beyond eof we only
update the in- memory file size in the write operation. Later when the I/O
operation, that flushes the cached data to disk completes, an I/O
completion routine will update the on-disk file size. The on-disk file
size will be updated to the maximum offset of the I/O or to the value of
the in-memory file size if the I/O includes eof.
SGI-PV: 958522
SGI-Modid: xfs-linux-melb:xfs-kern:28322a
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Tim Shimmin <tes@sgi.com>
2007-05-08 11:49:46 +08:00
|
|
|
|
2016-02-08 12:00:02 +08:00
|
|
|
/*
|
2017-03-03 07:02:51 +08:00
|
|
|
* Just clean up the in-memory strutures if the fs has been shut down.
|
2016-02-08 12:00:02 +08:00
|
|
|
*/
|
2017-03-03 07:02:51 +08:00
|
|
|
if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
|
2016-04-06 06:34:30 +08:00
|
|
|
error = -EIO;
|
2017-03-03 07:02:51 +08:00
|
|
|
goto done;
|
|
|
|
}
|
2011-08-24 13:59:25 +08:00
|
|
|
|
2016-10-04 00:11:35 +08:00
|
|
|
/*
|
2017-03-03 07:02:51 +08:00
|
|
|
* Clean up any COW blocks on an I/O error.
|
2016-10-04 00:11:35 +08:00
|
|
|
*/
|
2017-06-03 15:38:06 +08:00
|
|
|
error = blk_status_to_errno(ioend->io_bio->bi_status);
|
2017-03-03 07:02:51 +08:00
|
|
|
if (unlikely(error)) {
|
|
|
|
switch (ioend->io_type) {
|
|
|
|
case XFS_IO_COW:
|
|
|
|
xfs_reflink_cancel_cow_range(ip, offset, size, true);
|
|
|
|
break;
|
2016-10-04 00:11:35 +08:00
|
|
|
}
|
2017-03-03 07:02:51 +08:00
|
|
|
|
|
|
|
goto done;
|
2016-10-04 00:11:35 +08:00
|
|
|
}
|
|
|
|
|
2009-10-30 17:11:47 +08:00
|
|
|
/*
|
2017-03-03 07:02:51 +08:00
|
|
|
* Success: commit the COW or unwritten blocks if needed.
|
2009-10-30 17:11:47 +08:00
|
|
|
*/
|
2017-03-03 07:02:51 +08:00
|
|
|
switch (ioend->io_type) {
|
|
|
|
case XFS_IO_COW:
|
|
|
|
error = xfs_reflink_end_cow(ip, offset, size);
|
|
|
|
break;
|
|
|
|
case XFS_IO_UNWRITTEN:
|
2017-09-22 02:26:18 +08:00
|
|
|
/* writeback should never update isize */
|
|
|
|
error = xfs_iomap_write_unwritten(ip, offset, size, false);
|
2017-03-03 07:02:51 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ASSERT(!xfs_ioend_is_append(ioend) || ioend->io_append_trans);
|
|
|
|
break;
|
2009-10-30 17:11:47 +08:00
|
|
|
}
|
[XFS] Fix to prevent the notorious 'NULL files' problem after a crash.
The problem that has been addressed is that of synchronising updates of
the file size with writes that extend a file. Without the fix the update
of a file's size, as a result of a write beyond eof, is independent of
when the cached data is flushed to disk. Often the file size update would
be written to the filesystem log before the data is flushed to disk. When
a system crashes between these two events and the filesystem log is
replayed on mount the file's size will be set but since the contents never
made it to disk the file is full of holes. If some of the cached data was
flushed to disk then it may just be a section of the file at the end that
has holes.
There are existing fixes to help alleviate this problem, particularly in
the case where a file has been truncated, that force cached data to be
flushed to disk when the file is closed. If the system crashes while the
file(s) are still open then this flushing will never occur.
The fix that we have implemented is to introduce a second file size,
called the in-memory file size, that represents the current file size as
viewed by the user. The existing file size, called the on-disk file size,
is the one that get's written to the filesystem log and we only update it
when it is safe to do so. When we write to a file beyond eof we only
update the in- memory file size in the write operation. Later when the I/O
operation, that flushes the cached data to disk completes, an I/O
completion routine will update the on-disk file size. The on-disk file
size will be updated to the maximum offset of the I/O or to the value of
the in-memory file size if the I/O includes eof.
SGI-PV: 958522
SGI-Modid: xfs-linux-melb:xfs-kern:28322a
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Tim Shimmin <tes@sgi.com>
2007-05-08 11:49:46 +08:00
|
|
|
|
2011-08-24 13:59:25 +08:00
|
|
|
done:
|
2017-03-03 07:02:51 +08:00
|
|
|
if (ioend->io_append_trans)
|
|
|
|
error = xfs_setfilesize_ioend(ioend, error);
|
2016-04-06 06:34:30 +08:00
|
|
|
xfs_destroy_ioend(ioend, error);
|
2009-04-07 00:42:11 +08:00
|
|
|
}
|
|
|
|
|
2016-04-06 06:34:30 +08:00
|
|
|
STATIC void
|
|
|
|
xfs_end_bio(
|
|
|
|
struct bio *bio)
|
2005-09-02 14:58:49 +08:00
|
|
|
{
|
2016-04-06 06:34:30 +08:00
|
|
|
struct xfs_ioend *ioend = bio->bi_private;
|
|
|
|
struct xfs_mount *mp = XFS_I(ioend->io_inode)->i_mount;
|
2005-09-02 14:58:49 +08:00
|
|
|
|
2016-10-04 00:11:35 +08:00
|
|
|
if (ioend->io_type == XFS_IO_UNWRITTEN || ioend->io_type == XFS_IO_COW)
|
2016-04-06 06:34:30 +08:00
|
|
|
queue_work(mp->m_unwritten_workqueue, &ioend->io_work);
|
|
|
|
else if (ioend->io_append_trans)
|
|
|
|
queue_work(mp->m_data_workqueue, &ioend->io_work);
|
|
|
|
else
|
2017-06-03 15:38:06 +08:00
|
|
|
xfs_destroy_ioend(ioend, blk_status_to_errno(bio->bi_status));
|
2005-09-02 14:58:49 +08:00
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
STATIC int
|
|
|
|
xfs_map_blocks(
|
2018-07-12 13:25:59 +08:00
|
|
|
struct xfs_writepage_ctx *wpc,
|
2005-04-17 06:20:36 +08:00
|
|
|
struct inode *inode,
|
2018-07-12 13:25:59 +08:00
|
|
|
loff_t offset)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2010-12-10 16:42:20 +08:00
|
|
|
struct xfs_inode *ip = XFS_I(inode);
|
|
|
|
struct xfs_mount *mp = ip->i_mount;
|
2017-02-28 06:28:32 +08:00
|
|
|
ssize_t count = i_blocksize(inode);
|
2018-07-12 13:26:02 +08:00
|
|
|
xfs_fileoff_t offset_fsb = XFS_B_TO_FSBT(mp, offset), end_fsb;
|
2018-07-12 13:25:59 +08:00
|
|
|
struct xfs_bmbt_irec imap;
|
|
|
|
int whichfork = XFS_DATA_FORK;
|
2018-07-12 13:26:01 +08:00
|
|
|
struct xfs_iext_cursor icur;
|
2018-07-12 13:26:02 +08:00
|
|
|
bool imap_valid;
|
2010-12-10 16:42:20 +08:00
|
|
|
int error = 0;
|
|
|
|
|
2018-07-12 13:26:02 +08:00
|
|
|
/*
|
|
|
|
* We have to make sure the cached mapping is within EOF to protect
|
|
|
|
* against eofblocks trimming on file release leaving us with a stale
|
|
|
|
* mapping. Otherwise, a page for a subsequent file extending buffered
|
|
|
|
* write could get picked up by this writeback cycle and written to the
|
|
|
|
* wrong blocks.
|
|
|
|
*
|
|
|
|
* Note that what we really want here is a generic mapping invalidation
|
|
|
|
* mechanism to protect us from arbitrary extent modifying contexts, not
|
|
|
|
* just eofblocks.
|
|
|
|
*/
|
|
|
|
xfs_trim_extent_eof(&wpc->imap, ip);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* COW fork blocks can overlap data fork blocks even if the blocks
|
|
|
|
* aren't shared. COW I/O always takes precedent, so we must always
|
|
|
|
* check for overlap on reflink inodes unless the mapping is already a
|
|
|
|
* COW one.
|
|
|
|
*/
|
|
|
|
imap_valid = offset_fsb >= wpc->imap.br_startoff &&
|
|
|
|
offset_fsb < wpc->imap.br_startoff + wpc->imap.br_blockcount;
|
|
|
|
if (imap_valid &&
|
|
|
|
(!xfs_is_reflink_inode(ip) || wpc->io_type == XFS_IO_COW))
|
|
|
|
return 0;
|
|
|
|
|
2010-12-10 16:42:20 +08:00
|
|
|
if (XFS_FORCED_SHUTDOWN(mp))
|
2014-06-22 13:04:54 +08:00
|
|
|
return -EIO;
|
2010-12-10 16:42:20 +08:00
|
|
|
|
2018-07-12 13:26:02 +08:00
|
|
|
/*
|
|
|
|
* If we don't have a valid map, now it's time to get a new one for this
|
|
|
|
* offset. This will convert delayed allocations (including COW ones)
|
|
|
|
* into real extents. If we return without a valid map, it means we
|
|
|
|
* landed in a hole and we skip the block.
|
|
|
|
*/
|
2016-02-15 14:20:50 +08:00
|
|
|
xfs_ilock(ip, XFS_ILOCK_SHARED);
|
2010-12-10 16:42:21 +08:00
|
|
|
ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
|
|
|
|
(ip->i_df.if_flags & XFS_IFEXTENTS));
|
2012-06-08 13:44:53 +08:00
|
|
|
ASSERT(offset <= mp->m_super->s_maxbytes);
|
2010-12-10 16:42:21 +08:00
|
|
|
|
2018-07-12 13:26:01 +08:00
|
|
|
if (offset > mp->m_super->s_maxbytes - count)
|
|
|
|
count = mp->m_super->s_maxbytes - offset;
|
|
|
|
end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if this is offset is covered by a COW extents, and if yes use
|
|
|
|
* it directly instead of looking up anything in the data fork.
|
|
|
|
*/
|
2018-07-12 13:25:59 +08:00
|
|
|
if (xfs_is_reflink_inode(ip) &&
|
2018-07-12 13:26:01 +08:00
|
|
|
xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &imap) &&
|
|
|
|
imap.br_startoff <= offset_fsb) {
|
2018-07-12 13:25:59 +08:00
|
|
|
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
|
|
|
/*
|
|
|
|
* Truncate can race with writeback since writeback doesn't
|
|
|
|
* take the iolock and truncate decreases the file size before
|
|
|
|
* it starts truncating the pages between new_size and old_size.
|
|
|
|
* Therefore, we can end up in the situation where writeback
|
|
|
|
* gets a CoW fork mapping but the truncate makes the mapping
|
|
|
|
* invalid and we end up in here trying to get a new mapping.
|
|
|
|
* bail out here so that we simply never get a valid mapping
|
|
|
|
* and so we drop the write altogether. The page truncation
|
|
|
|
* will kill the contents anyway.
|
|
|
|
*/
|
|
|
|
if (offset > i_size_read(inode)) {
|
|
|
|
wpc->io_type = XFS_IO_HOLE;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
whichfork = XFS_COW_FORK;
|
|
|
|
wpc->io_type = XFS_IO_COW;
|
|
|
|
goto allocate_blocks;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Map valid and no COW extent in the way? We're done.
|
|
|
|
*/
|
2018-07-12 13:26:02 +08:00
|
|
|
if (imap_valid) {
|
2018-07-12 13:25:59 +08:00
|
|
|
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we don't have a valid map, now it's time to get a new one for this
|
|
|
|
* offset. This will convert delayed allocations (including COW ones)
|
|
|
|
* into real extents.
|
|
|
|
*/
|
2018-07-12 13:26:02 +08:00
|
|
|
if (!xfs_iext_lookup_extent(ip, &ip->i_df, offset_fsb, &icur, &imap))
|
|
|
|
imap.br_startoff = end_fsb; /* fake a hole past EOF */
|
2010-12-10 16:42:21 +08:00
|
|
|
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
2010-12-10 16:42:20 +08:00
|
|
|
|
2018-07-12 13:26:02 +08:00
|
|
|
if (imap.br_startoff > offset_fsb) {
|
|
|
|
/* landed in a hole or beyond EOF */
|
|
|
|
imap.br_blockcount = imap.br_startoff - offset_fsb;
|
2018-07-12 13:25:59 +08:00
|
|
|
imap.br_startoff = offset_fsb;
|
|
|
|
imap.br_startblock = HOLESTARTBLOCK;
|
|
|
|
wpc->io_type = XFS_IO_HOLE;
|
xfs: make xfs_writepage_map extent map centric
xfs_writepage_map() iterates over the bufferheads on a page to decide
what sort of IO to do and what actions to take. However, when it comes
to reflink and deciding when it needs to execute a COW operation, we no
longer look at the bufferhead state but instead we ignore than and look
up internal state held in the COW fork extent list.
This means xfs_writepage_map() is somewhat confused. It does stuff, then
ignores it, then tries to handle the impedence mismatch by shovelling the
results inside the existing mapping code. It works, but it's a bit of a
mess and it makes it hard to fix the cached map bug that the writepage
code currently has.
To unify the two different mechanisms, we first have to choose a direction.
That's already been set - we're de-emphasising bufferheads so they are no
longer a control structure as we need to do taht to allow for eventual
removal. Hence we need to move away from looking at bufferhead state to
determine what operations we need to perform.
We can't completely get rid of bufferheads yet - they do contain some
state that is absolutely necessary, such as whether that part of the page
contains valid data or not (buffer_uptodate()). Other state in the
bufferhead is redundant:
BH_dirty - the page is dirty, so we can ignore this and just
write it
BH_delay - we have delalloc extent info in the DATA fork extent
tree
BH_unwritten - same as BH_delay
BH_mapped - indicates we've already used it once for IO and it is
mapped to a disk address. Needs to be ignored for COW
blocks.
The BH_mapped flag is an interesting case - it's supposed to indicate that
it's already mapped to disk and so we can just use it "as is". In theory,
we don't even have to do an extent lookup to find where to write it too,
but we have to do that anyway to determine we are actually writing over a
valid extent. Hence it's not even serving the purpose of avoiding a an
extent lookup during writeback, and so we can pretty much ignore it.
Especially as we have to ignore it for COW operations...
Therefore, use the extent map as the source of information to tell us
what actions we need to take and what sort of IO we should perform. The
first step is to have xfs_map_blocks() set the io type according to what
it looks up. This means it can easily handle both normal overwrite and
COW cases. The only thing we also need to add is the ability to return
hole mappings.
We need to return and cache hole mappings now for the case of multiple
blocks per page. We no longer use the BH_mapped to indicate a block over
a hole, so we have to get that info from xfs_map_blocks(). We cache it so
that holes that span two pages don't need separate lookups. This allows us
to avoid ever doing write IO over a hole, too.
Now that we have xfs_map_blocks() returning both a cached map and the type
of IO we need to perform, we can rewrite xfs_writepage_map() to drop all
the bufferhead control. It's also much simplified because it doesn't need
to explicitly handle COW operations. Instead of iterating bufferheads, it
iterates blocks within the page and then looks up what per-block state is
required from the appropriate bufferhead. It then validates the cached
map, and if it's not valid, we get a new map. If we don't get a valid map
or it's over a hole, we skip the block.
At this point, we have to remap the bufferhead via xfs_map_at_offset().
As previously noted, we had to do this even if the buffer was already
mapped as the mapping would be stale for XFS_IO_DELALLOC, XFS_IO_UNWRITTEN
and XFS_IO_COW IO types. With xfs_map_blocks() now controlling the type,
even XFS_IO_OVERWRITE types need remapping, as converted-but-not-yet-
written delalloc extents beyond EOF can be reported at XFS_IO_OVERWRITE.
Bufferheads that span such regions still need their BH_Delay flags cleared
and their block numbers calculated, so we now unconditionally map each
bufferhead before submission.
But wait! There's more - remember the old "treat unwritten extents as
holes on read" hack? Yeah, that means we can have a dirty page with
unmapped, unwritten bufferheads that contain data! What makes these so
special is that the unwritten "hole" bufferheads do not have a valid block
device pointer, so if we attempt to write them xfs_add_to_ioend() blows
up. So we make xfs_map_at_offset() do the "realtime or data device"
lookup from the inode and ignore what was or wasn't put into the
bufferhead when the buffer was instantiated.
The astute reader will have realised by now that this code treats
unwritten extents in multiple-blocks-per-page situations differently.
If we get any combination of unwritten blocks on a dirty page that contain
valid data in the page, we're going to convert them to real extents. This
can actually be a win, because it means that pages with interleaving
unwritten and written blocks will get converted to a single written extent
with zeros replacing the interspersed unwritten blocks. This is actually
good for reducing extent list and conversion overhead, and it means we
issue a contiguous IO instead of lots of little ones. The downside is
that we use up a little extra IO bandwidth. Neither of these seem like a
bad thing given that spinning disks are seek sensitive, and SSDs/pmem have
bandwidth to burn and the lower Io latency/CPU overhead of fewer, larger
IOs will result in better performance on them...
As a result of all this, the only state we actually care about from the
bufferhead is a single flag - BH_Uptodate. We still use the bufferhead to
pass some information to the bio via xfs_add_to_ioend(), but that is
trivial to separate and pass explicitly. This means we really only need
1 bit of state per block per page from the buffered write path in the
writeback path. Everything else we do with the bufferhead is purely to
make the buffered IO front end continue to work correctly. i.e we've
pretty much marginalised bufferheads in the writeback path completely.
Signed-off-By: Dave Chinner <dchinner@redhat.com>
[hch: forward port, refactor and split off bits into other commits]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
2018-07-12 13:26:00 +08:00
|
|
|
} else {
|
|
|
|
if (isnullstartblock(imap.br_startblock)) {
|
|
|
|
/* got a delalloc extent */
|
|
|
|
wpc->io_type = XFS_IO_DELALLOC;
|
|
|
|
goto allocate_blocks;
|
|
|
|
}
|
2018-07-12 13:25:59 +08:00
|
|
|
|
xfs: make xfs_writepage_map extent map centric
xfs_writepage_map() iterates over the bufferheads on a page to decide
what sort of IO to do and what actions to take. However, when it comes
to reflink and deciding when it needs to execute a COW operation, we no
longer look at the bufferhead state but instead we ignore than and look
up internal state held in the COW fork extent list.
This means xfs_writepage_map() is somewhat confused. It does stuff, then
ignores it, then tries to handle the impedence mismatch by shovelling the
results inside the existing mapping code. It works, but it's a bit of a
mess and it makes it hard to fix the cached map bug that the writepage
code currently has.
To unify the two different mechanisms, we first have to choose a direction.
That's already been set - we're de-emphasising bufferheads so they are no
longer a control structure as we need to do taht to allow for eventual
removal. Hence we need to move away from looking at bufferhead state to
determine what operations we need to perform.
We can't completely get rid of bufferheads yet - they do contain some
state that is absolutely necessary, such as whether that part of the page
contains valid data or not (buffer_uptodate()). Other state in the
bufferhead is redundant:
BH_dirty - the page is dirty, so we can ignore this and just
write it
BH_delay - we have delalloc extent info in the DATA fork extent
tree
BH_unwritten - same as BH_delay
BH_mapped - indicates we've already used it once for IO and it is
mapped to a disk address. Needs to be ignored for COW
blocks.
The BH_mapped flag is an interesting case - it's supposed to indicate that
it's already mapped to disk and so we can just use it "as is". In theory,
we don't even have to do an extent lookup to find where to write it too,
but we have to do that anyway to determine we are actually writing over a
valid extent. Hence it's not even serving the purpose of avoiding a an
extent lookup during writeback, and so we can pretty much ignore it.
Especially as we have to ignore it for COW operations...
Therefore, use the extent map as the source of information to tell us
what actions we need to take and what sort of IO we should perform. The
first step is to have xfs_map_blocks() set the io type according to what
it looks up. This means it can easily handle both normal overwrite and
COW cases. The only thing we also need to add is the ability to return
hole mappings.
We need to return and cache hole mappings now for the case of multiple
blocks per page. We no longer use the BH_mapped to indicate a block over
a hole, so we have to get that info from xfs_map_blocks(). We cache it so
that holes that span two pages don't need separate lookups. This allows us
to avoid ever doing write IO over a hole, too.
Now that we have xfs_map_blocks() returning both a cached map and the type
of IO we need to perform, we can rewrite xfs_writepage_map() to drop all
the bufferhead control. It's also much simplified because it doesn't need
to explicitly handle COW operations. Instead of iterating bufferheads, it
iterates blocks within the page and then looks up what per-block state is
required from the appropriate bufferhead. It then validates the cached
map, and if it's not valid, we get a new map. If we don't get a valid map
or it's over a hole, we skip the block.
At this point, we have to remap the bufferhead via xfs_map_at_offset().
As previously noted, we had to do this even if the buffer was already
mapped as the mapping would be stale for XFS_IO_DELALLOC, XFS_IO_UNWRITTEN
and XFS_IO_COW IO types. With xfs_map_blocks() now controlling the type,
even XFS_IO_OVERWRITE types need remapping, as converted-but-not-yet-
written delalloc extents beyond EOF can be reported at XFS_IO_OVERWRITE.
Bufferheads that span such regions still need their BH_Delay flags cleared
and their block numbers calculated, so we now unconditionally map each
bufferhead before submission.
But wait! There's more - remember the old "treat unwritten extents as
holes on read" hack? Yeah, that means we can have a dirty page with
unmapped, unwritten bufferheads that contain data! What makes these so
special is that the unwritten "hole" bufferheads do not have a valid block
device pointer, so if we attempt to write them xfs_add_to_ioend() blows
up. So we make xfs_map_at_offset() do the "realtime or data device"
lookup from the inode and ignore what was or wasn't put into the
bufferhead when the buffer was instantiated.
The astute reader will have realised by now that this code treats
unwritten extents in multiple-blocks-per-page situations differently.
If we get any combination of unwritten blocks on a dirty page that contain
valid data in the page, we're going to convert them to real extents. This
can actually be a win, because it means that pages with interleaving
unwritten and written blocks will get converted to a single written extent
with zeros replacing the interspersed unwritten blocks. This is actually
good for reducing extent list and conversion overhead, and it means we
issue a contiguous IO instead of lots of little ones. The downside is
that we use up a little extra IO bandwidth. Neither of these seem like a
bad thing given that spinning disks are seek sensitive, and SSDs/pmem have
bandwidth to burn and the lower Io latency/CPU overhead of fewer, larger
IOs will result in better performance on them...
As a result of all this, the only state we actually care about from the
bufferhead is a single flag - BH_Uptodate. We still use the bufferhead to
pass some information to the bio via xfs_add_to_ioend(), but that is
trivial to separate and pass explicitly. This means we really only need
1 bit of state per block per page from the buffered write path in the
writeback path. Everything else we do with the bufferhead is purely to
make the buffered IO front end continue to work correctly. i.e we've
pretty much marginalised bufferheads in the writeback path completely.
Signed-off-By: Dave Chinner <dchinner@redhat.com>
[hch: forward port, refactor and split off bits into other commits]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
2018-07-12 13:26:00 +08:00
|
|
|
if (imap.br_state == XFS_EXT_UNWRITTEN)
|
|
|
|
wpc->io_type = XFS_IO_UNWRITTEN;
|
|
|
|
else
|
|
|
|
wpc->io_type = XFS_IO_OVERWRITE;
|
2010-12-10 16:42:21 +08:00
|
|
|
}
|
xfs: make xfs_writepage_map extent map centric
xfs_writepage_map() iterates over the bufferheads on a page to decide
what sort of IO to do and what actions to take. However, when it comes
to reflink and deciding when it needs to execute a COW operation, we no
longer look at the bufferhead state but instead we ignore than and look
up internal state held in the COW fork extent list.
This means xfs_writepage_map() is somewhat confused. It does stuff, then
ignores it, then tries to handle the impedence mismatch by shovelling the
results inside the existing mapping code. It works, but it's a bit of a
mess and it makes it hard to fix the cached map bug that the writepage
code currently has.
To unify the two different mechanisms, we first have to choose a direction.
That's already been set - we're de-emphasising bufferheads so they are no
longer a control structure as we need to do taht to allow for eventual
removal. Hence we need to move away from looking at bufferhead state to
determine what operations we need to perform.
We can't completely get rid of bufferheads yet - they do contain some
state that is absolutely necessary, such as whether that part of the page
contains valid data or not (buffer_uptodate()). Other state in the
bufferhead is redundant:
BH_dirty - the page is dirty, so we can ignore this and just
write it
BH_delay - we have delalloc extent info in the DATA fork extent
tree
BH_unwritten - same as BH_delay
BH_mapped - indicates we've already used it once for IO and it is
mapped to a disk address. Needs to be ignored for COW
blocks.
The BH_mapped flag is an interesting case - it's supposed to indicate that
it's already mapped to disk and so we can just use it "as is". In theory,
we don't even have to do an extent lookup to find where to write it too,
but we have to do that anyway to determine we are actually writing over a
valid extent. Hence it's not even serving the purpose of avoiding a an
extent lookup during writeback, and so we can pretty much ignore it.
Especially as we have to ignore it for COW operations...
Therefore, use the extent map as the source of information to tell us
what actions we need to take and what sort of IO we should perform. The
first step is to have xfs_map_blocks() set the io type according to what
it looks up. This means it can easily handle both normal overwrite and
COW cases. The only thing we also need to add is the ability to return
hole mappings.
We need to return and cache hole mappings now for the case of multiple
blocks per page. We no longer use the BH_mapped to indicate a block over
a hole, so we have to get that info from xfs_map_blocks(). We cache it so
that holes that span two pages don't need separate lookups. This allows us
to avoid ever doing write IO over a hole, too.
Now that we have xfs_map_blocks() returning both a cached map and the type
of IO we need to perform, we can rewrite xfs_writepage_map() to drop all
the bufferhead control. It's also much simplified because it doesn't need
to explicitly handle COW operations. Instead of iterating bufferheads, it
iterates blocks within the page and then looks up what per-block state is
required from the appropriate bufferhead. It then validates the cached
map, and if it's not valid, we get a new map. If we don't get a valid map
or it's over a hole, we skip the block.
At this point, we have to remap the bufferhead via xfs_map_at_offset().
As previously noted, we had to do this even if the buffer was already
mapped as the mapping would be stale for XFS_IO_DELALLOC, XFS_IO_UNWRITTEN
and XFS_IO_COW IO types. With xfs_map_blocks() now controlling the type,
even XFS_IO_OVERWRITE types need remapping, as converted-but-not-yet-
written delalloc extents beyond EOF can be reported at XFS_IO_OVERWRITE.
Bufferheads that span such regions still need their BH_Delay flags cleared
and their block numbers calculated, so we now unconditionally map each
bufferhead before submission.
But wait! There's more - remember the old "treat unwritten extents as
holes on read" hack? Yeah, that means we can have a dirty page with
unmapped, unwritten bufferheads that contain data! What makes these so
special is that the unwritten "hole" bufferheads do not have a valid block
device pointer, so if we attempt to write them xfs_add_to_ioend() blows
up. So we make xfs_map_at_offset() do the "realtime or data device"
lookup from the inode and ignore what was or wasn't put into the
bufferhead when the buffer was instantiated.
The astute reader will have realised by now that this code treats
unwritten extents in multiple-blocks-per-page situations differently.
If we get any combination of unwritten blocks on a dirty page that contain
valid data in the page, we're going to convert them to real extents. This
can actually be a win, because it means that pages with interleaving
unwritten and written blocks will get converted to a single written extent
with zeros replacing the interspersed unwritten blocks. This is actually
good for reducing extent list and conversion overhead, and it means we
issue a contiguous IO instead of lots of little ones. The downside is
that we use up a little extra IO bandwidth. Neither of these seem like a
bad thing given that spinning disks are seek sensitive, and SSDs/pmem have
bandwidth to burn and the lower Io latency/CPU overhead of fewer, larger
IOs will result in better performance on them...
As a result of all this, the only state we actually care about from the
bufferhead is a single flag - BH_Uptodate. We still use the bufferhead to
pass some information to the bio via xfs_add_to_ioend(), but that is
trivial to separate and pass explicitly. This means we really only need
1 bit of state per block per page from the buffered write path in the
writeback path. Everything else we do with the bufferhead is purely to
make the buffered IO front end continue to work correctly. i.e we've
pretty much marginalised bufferheads in the writeback path completely.
Signed-off-By: Dave Chinner <dchinner@redhat.com>
[hch: forward port, refactor and split off bits into other commits]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
2018-07-12 13:26:00 +08:00
|
|
|
|
2018-07-12 13:25:59 +08:00
|
|
|
wpc->imap = imap;
|
|
|
|
trace_xfs_map_blocks_found(ip, offset, count, wpc->io_type, &imap);
|
|
|
|
return 0;
|
|
|
|
allocate_blocks:
|
|
|
|
error = xfs_iomap_write_allocate(ip, whichfork, offset, &imap);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
wpc->imap = imap;
|
|
|
|
trace_xfs_map_blocks_alloc(ip, offset, count, wpc->io_type, &imap);
|
2010-12-10 16:42:21 +08:00
|
|
|
return 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-01-11 12:40:13 +08:00
|
|
|
/*
|
2016-04-06 06:11:25 +08:00
|
|
|
* Submit the bio for an ioend. We are passed an ioend with a bio attached to
|
|
|
|
* it, and we submit that bio. The ioend may be used for multiple bio
|
|
|
|
* submissions, so we only want to allocate an append transaction for the ioend
|
|
|
|
* once. In the case of multiple bio submission, each bio will take an IO
|
|
|
|
* reference to the ioend to ensure that the ioend completion is only done once
|
|
|
|
* all bios have been submitted and the ioend is really done.
|
xfs: fix broken error handling in xfs_vm_writepage
When we shut down the filesystem, it might first be detected in
writeback when we are allocating a inode size transaction. This
happens after we have moved all the pages into the writeback state
and unlocked them. Unfortunately, if we fail to set up the
transaction we then abort writeback and try to invalidate the
current page. This then triggers are BUG() in block_invalidatepage()
because we are trying to invalidate an unlocked page.
Fixing this is a bit of a chicken and egg problem - we can't
allocate the transaction until we've clustered all the pages into
the IO and we know the size of it (i.e. whether the last block of
the IO is beyond the current EOF or not). However, we don't want to
hold pages locked for long periods of time, especially while we lock
other pages to cluster them into the write.
To fix this, we need to make a clear delineation in writeback where
errors can only be handled by IO completion processing. That is,
once we have marked a page for writeback and unlocked it, we have to
report errors via IO completion because we've already started the
IO. We may not have submitted any IO, but we've changed the page
state to indicate that it is under IO so we must now use the IO
completion path to report errors.
To do this, add an error field to xfs_submit_ioend() to pass it the
error that occurred during the building on the ioend chain. When
this is non-zero, mark each ioend with the error and call
xfs_finish_ioend() directly rather than building bios. This will
immediately push the ioends through completion processing with the
error that has occurred.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
2012-11-12 19:09:45 +08:00
|
|
|
*
|
|
|
|
* If @fail is non-zero, it means that we have a situation where some part of
|
|
|
|
* the submission process has failed after we have marked paged for writeback
|
2016-04-06 06:11:25 +08:00
|
|
|
* and unlocked them. In this situation, we need to fail the bio and ioend
|
|
|
|
* rather than submit it to IO. This typically only happens on a filesystem
|
|
|
|
* shutdown.
|
2006-01-11 12:40:13 +08:00
|
|
|
*/
|
2016-02-15 14:23:12 +08:00
|
|
|
STATIC int
|
2006-01-11 12:40:13 +08:00
|
|
|
xfs_submit_ioend(
|
2009-10-30 17:09:15 +08:00
|
|
|
struct writeback_control *wbc,
|
2016-04-06 06:34:30 +08:00
|
|
|
struct xfs_ioend *ioend,
|
2016-02-15 14:23:12 +08:00
|
|
|
int status)
|
2006-01-11 12:40:13 +08:00
|
|
|
{
|
2017-02-03 07:14:02 +08:00
|
|
|
/* Convert CoW extents to regular */
|
|
|
|
if (!status && ioend->io_type == XFS_IO_COW) {
|
2018-06-07 22:46:42 +08:00
|
|
|
/*
|
|
|
|
* Yuk. This can do memory allocation, but is not a
|
|
|
|
* transactional operation so everything is done in GFP_KERNEL
|
|
|
|
* context. That can deadlock, because we hold pages in
|
|
|
|
* writeback state and GFP_KERNEL allocations can block on them.
|
|
|
|
* Hence we must operate in nofs conditions here.
|
|
|
|
*/
|
|
|
|
unsigned nofs_flag;
|
|
|
|
|
|
|
|
nofs_flag = memalloc_nofs_save();
|
2017-02-03 07:14:02 +08:00
|
|
|
status = xfs_reflink_convert_cow(XFS_I(ioend->io_inode),
|
|
|
|
ioend->io_offset, ioend->io_size);
|
2018-06-07 22:46:42 +08:00
|
|
|
memalloc_nofs_restore(nofs_flag);
|
2017-02-03 07:14:02 +08:00
|
|
|
}
|
|
|
|
|
2016-02-15 14:23:12 +08:00
|
|
|
/* Reserve log space if we might write beyond the on-disk inode size. */
|
|
|
|
if (!status &&
|
2016-04-06 06:34:30 +08:00
|
|
|
ioend->io_type != XFS_IO_UNWRITTEN &&
|
2016-04-06 06:11:25 +08:00
|
|
|
xfs_ioend_is_append(ioend) &&
|
|
|
|
!ioend->io_append_trans)
|
2016-02-15 14:23:12 +08:00
|
|
|
status = xfs_setfilesize_trans_alloc(ioend);
|
2016-04-06 06:11:25 +08:00
|
|
|
|
2016-04-06 06:34:30 +08:00
|
|
|
ioend->io_bio->bi_private = ioend;
|
|
|
|
ioend->io_bio->bi_end_io = xfs_end_bio;
|
2016-11-02 00:00:38 +08:00
|
|
|
ioend->io_bio->bi_opf = REQ_OP_WRITE | wbc_to_write_flags(wbc);
|
2016-11-01 21:40:10 +08:00
|
|
|
|
2016-02-15 14:23:12 +08:00
|
|
|
/*
|
|
|
|
* If we are failing the IO now, just mark the ioend with an
|
|
|
|
* error and finish it. This will run IO completion immediately
|
|
|
|
* as there is only one reference to the ioend at this point in
|
|
|
|
* time.
|
|
|
|
*/
|
|
|
|
if (status) {
|
2017-06-03 15:38:06 +08:00
|
|
|
ioend->io_bio->bi_status = errno_to_blk_status(status);
|
2016-04-06 06:34:30 +08:00
|
|
|
bio_endio(ioend->io_bio);
|
2016-02-15 14:23:12 +08:00
|
|
|
return status;
|
|
|
|
}
|
2006-01-18 10:38:12 +08:00
|
|
|
|
2017-06-27 23:34:01 +08:00
|
|
|
ioend->io_bio->bi_write_hint = ioend->io_inode->i_write_hint;
|
2016-06-06 03:31:41 +08:00
|
|
|
submit_bio(ioend->io_bio);
|
2016-02-15 14:23:12 +08:00
|
|
|
return 0;
|
2006-01-11 12:40:13 +08:00
|
|
|
}
|
|
|
|
|
2016-04-06 06:34:30 +08:00
|
|
|
static struct xfs_ioend *
|
|
|
|
xfs_alloc_ioend(
|
|
|
|
struct inode *inode,
|
|
|
|
unsigned int type,
|
|
|
|
xfs_off_t offset,
|
2018-07-12 13:26:02 +08:00
|
|
|
struct block_device *bdev,
|
|
|
|
sector_t sector)
|
2016-04-06 06:34:30 +08:00
|
|
|
{
|
|
|
|
struct xfs_ioend *ioend;
|
|
|
|
struct bio *bio;
|
2006-01-11 12:40:13 +08:00
|
|
|
|
2018-05-21 06:25:57 +08:00
|
|
|
bio = bio_alloc_bioset(GFP_NOFS, BIO_MAX_PAGES, &xfs_ioend_bioset);
|
2018-07-12 13:26:02 +08:00
|
|
|
bio_set_dev(bio, bdev);
|
|
|
|
bio->bi_iter.bi_sector = sector;
|
2016-04-06 06:34:30 +08:00
|
|
|
|
|
|
|
ioend = container_of(bio, struct xfs_ioend, io_inline_bio);
|
|
|
|
INIT_LIST_HEAD(&ioend->io_list);
|
|
|
|
ioend->io_type = type;
|
|
|
|
ioend->io_inode = inode;
|
|
|
|
ioend->io_size = 0;
|
|
|
|
ioend->io_offset = offset;
|
|
|
|
INIT_WORK(&ioend->io_work, xfs_end_io);
|
|
|
|
ioend->io_append_trans = NULL;
|
|
|
|
ioend->io_bio = bio;
|
|
|
|
return ioend;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate a new bio, and chain the old bio to the new one.
|
|
|
|
*
|
|
|
|
* Note that we have to do perform the chaining in this unintuitive order
|
|
|
|
* so that the bi_private linkage is set up in the right direction for the
|
|
|
|
* traversal in xfs_destroy_ioend().
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
xfs_chain_bio(
|
|
|
|
struct xfs_ioend *ioend,
|
|
|
|
struct writeback_control *wbc,
|
2018-07-12 13:26:02 +08:00
|
|
|
struct block_device *bdev,
|
|
|
|
sector_t sector)
|
2016-04-06 06:34:30 +08:00
|
|
|
{
|
|
|
|
struct bio *new;
|
|
|
|
|
|
|
|
new = bio_alloc(GFP_NOFS, BIO_MAX_PAGES);
|
2018-07-12 13:26:02 +08:00
|
|
|
bio_set_dev(new, bdev);
|
|
|
|
new->bi_iter.bi_sector = sector;
|
2016-04-06 06:34:30 +08:00
|
|
|
bio_chain(ioend->io_bio, new);
|
|
|
|
bio_get(ioend->io_bio); /* for xfs_destroy_ioend */
|
2016-11-02 00:00:38 +08:00
|
|
|
ioend->io_bio->bi_opf = REQ_OP_WRITE | wbc_to_write_flags(wbc);
|
2017-06-27 23:34:01 +08:00
|
|
|
ioend->io_bio->bi_write_hint = ioend->io_inode->i_write_hint;
|
2016-06-06 03:31:41 +08:00
|
|
|
submit_bio(ioend->io_bio);
|
2016-04-06 06:34:30 +08:00
|
|
|
ioend->io_bio = new;
|
2006-01-11 12:40:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2018-07-12 13:26:02 +08:00
|
|
|
* Test to see if we have an existing ioend structure that we could append to
|
|
|
|
* first, otherwise finish off the current ioend and start another.
|
2006-01-11 12:40:13 +08:00
|
|
|
*/
|
|
|
|
STATIC void
|
|
|
|
xfs_add_to_ioend(
|
|
|
|
struct inode *inode,
|
2006-01-11 17:49:16 +08:00
|
|
|
xfs_off_t offset,
|
2018-07-12 13:26:02 +08:00
|
|
|
struct page *page,
|
2018-07-12 13:26:05 +08:00
|
|
|
struct iomap_page *iop,
|
2016-02-15 14:23:12 +08:00
|
|
|
struct xfs_writepage_ctx *wpc,
|
2016-04-06 06:11:25 +08:00
|
|
|
struct writeback_control *wbc,
|
2016-02-15 14:23:12 +08:00
|
|
|
struct list_head *iolist)
|
2006-01-11 12:40:13 +08:00
|
|
|
{
|
2018-07-12 13:26:02 +08:00
|
|
|
struct xfs_inode *ip = XFS_I(inode);
|
|
|
|
struct xfs_mount *mp = ip->i_mount;
|
|
|
|
struct block_device *bdev = xfs_find_bdev_for_inode(inode);
|
|
|
|
unsigned len = i_blocksize(inode);
|
|
|
|
unsigned poff = offset & (PAGE_SIZE - 1);
|
|
|
|
sector_t sector;
|
|
|
|
|
|
|
|
sector = xfs_fsb_to_db(ip, wpc->imap.br_startblock) +
|
|
|
|
((offset - XFS_FSB_TO_B(mp, wpc->imap.br_startoff)) >> 9);
|
|
|
|
|
2016-02-15 14:21:19 +08:00
|
|
|
if (!wpc->ioend || wpc->io_type != wpc->ioend->io_type ||
|
2018-07-12 13:26:02 +08:00
|
|
|
sector != bio_end_sector(wpc->ioend->io_bio) ||
|
2016-03-07 06:32:14 +08:00
|
|
|
offset != wpc->ioend->io_offset + wpc->ioend->io_size) {
|
2016-02-15 14:23:12 +08:00
|
|
|
if (wpc->ioend)
|
|
|
|
list_add(&wpc->ioend->io_list, iolist);
|
2018-07-12 13:26:02 +08:00
|
|
|
wpc->ioend = xfs_alloc_ioend(inode, wpc->io_type, offset,
|
|
|
|
bdev, sector);
|
2006-01-11 12:40:13 +08:00
|
|
|
}
|
|
|
|
|
2018-07-12 13:26:05 +08:00
|
|
|
if (!__bio_try_merge_page(wpc->ioend->io_bio, page, len, poff)) {
|
|
|
|
if (iop)
|
|
|
|
atomic_inc(&iop->write_count);
|
|
|
|
if (bio_full(wpc->ioend->io_bio))
|
|
|
|
xfs_chain_bio(wpc->ioend, wbc, bdev, sector);
|
|
|
|
__bio_add_page(wpc->ioend->io_bio, page, len, poff);
|
|
|
|
}
|
2016-04-06 06:11:25 +08:00
|
|
|
|
2018-07-12 13:26:02 +08:00
|
|
|
wpc->ioend->io_size += len;
|
2006-01-11 12:40:13 +08:00
|
|
|
}
|
|
|
|
|
2010-03-05 10:00:42 +08:00
|
|
|
STATIC void
|
|
|
|
xfs_vm_invalidatepage(
|
|
|
|
struct page *page,
|
2013-05-22 11:17:23 +08:00
|
|
|
unsigned int offset,
|
|
|
|
unsigned int length)
|
2010-03-05 10:00:42 +08:00
|
|
|
{
|
2018-07-12 13:26:05 +08:00
|
|
|
trace_xfs_invalidatepage(page->mapping->host, page, offset, length);
|
|
|
|
iomap_invalidatepage(page, offset, length);
|
2010-03-05 10:00:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2018-07-12 13:26:05 +08:00
|
|
|
* If the page has delalloc blocks on it, we need to punch them out before we
|
|
|
|
* invalidate the page. If we don't, we leave a stale delalloc mapping on the
|
|
|
|
* inode that can trip up a later direct I/O read operation on the same region.
|
2010-03-05 10:00:42 +08:00
|
|
|
*
|
2018-07-12 13:26:05 +08:00
|
|
|
* We prevent this by truncating away the delalloc regions on the page. Because
|
|
|
|
* they are delalloc, we can do this without needing a transaction. Indeed - if
|
|
|
|
* we get ENOSPC errors, we have to be able to do this truncation without a
|
|
|
|
* transaction as there is no space left for block reservation (typically why we
|
|
|
|
* see a ENOSPC in writeback).
|
2010-03-05 10:00:42 +08:00
|
|
|
*/
|
|
|
|
STATIC void
|
|
|
|
xfs_aops_discard_page(
|
|
|
|
struct page *page)
|
|
|
|
{
|
|
|
|
struct inode *inode = page->mapping->host;
|
|
|
|
struct xfs_inode *ip = XFS_I(inode);
|
2018-07-12 13:25:57 +08:00
|
|
|
struct xfs_mount *mp = ip->i_mount;
|
2010-03-05 10:00:42 +08:00
|
|
|
loff_t offset = page_offset(page);
|
2018-07-12 13:25:57 +08:00
|
|
|
xfs_fileoff_t start_fsb = XFS_B_TO_FSBT(mp, offset);
|
|
|
|
int error;
|
2010-03-05 10:00:42 +08:00
|
|
|
|
2018-07-12 13:25:57 +08:00
|
|
|
if (XFS_FORCED_SHUTDOWN(mp))
|
2010-03-15 10:36:35 +08:00
|
|
|
goto out_invalidate;
|
|
|
|
|
2018-07-12 13:25:57 +08:00
|
|
|
xfs_alert(mp,
|
2018-01-10 04:02:55 +08:00
|
|
|
"page discard on page "PTR_FMT", inode 0x%llx, offset %llu.",
|
2010-03-05 10:00:42 +08:00
|
|
|
page, ip->i_ino, offset);
|
|
|
|
|
2018-07-12 13:25:57 +08:00
|
|
|
error = xfs_bmap_punch_delalloc_range(ip, start_fsb,
|
|
|
|
PAGE_SIZE / i_blocksize(inode));
|
|
|
|
if (error && !XFS_FORCED_SHUTDOWN(mp))
|
|
|
|
xfs_alert(mp, "page discard unable to remove delalloc mapping.");
|
2010-03-05 10:00:42 +08:00
|
|
|
out_invalidate:
|
mm, fs: get rid of PAGE_CACHE_* and page_cache_{get,release} macros
PAGE_CACHE_{SIZE,SHIFT,MASK,ALIGN} macros were introduced *long* time
ago with promise that one day it will be possible to implement page
cache with bigger chunks than PAGE_SIZE.
This promise never materialized. And unlikely will.
We have many places where PAGE_CACHE_SIZE assumed to be equal to
PAGE_SIZE. And it's constant source of confusion on whether
PAGE_CACHE_* or PAGE_* constant should be used in a particular case,
especially on the border between fs and mm.
Global switching to PAGE_CACHE_SIZE != PAGE_SIZE would cause to much
breakage to be doable.
Let's stop pretending that pages in page cache are special. They are
not.
The changes are pretty straight-forward:
- <foo> << (PAGE_CACHE_SHIFT - PAGE_SHIFT) -> <foo>;
- <foo> >> (PAGE_CACHE_SHIFT - PAGE_SHIFT) -> <foo>;
- PAGE_CACHE_{SIZE,SHIFT,MASK,ALIGN} -> PAGE_{SIZE,SHIFT,MASK,ALIGN};
- page_cache_get() -> get_page();
- page_cache_release() -> put_page();
This patch contains automated changes generated with coccinelle using
script below. For some reason, coccinelle doesn't patch header files.
I've called spatch for them manually.
The only adjustment after coccinelle is revert of changes to
PAGE_CAHCE_ALIGN definition: we are going to drop it later.
There are few places in the code where coccinelle didn't reach. I'll
fix them manually in a separate patch. Comments and documentation also
will be addressed with the separate patch.
virtual patch
@@
expression E;
@@
- E << (PAGE_CACHE_SHIFT - PAGE_SHIFT)
+ E
@@
expression E;
@@
- E >> (PAGE_CACHE_SHIFT - PAGE_SHIFT)
+ E
@@
@@
- PAGE_CACHE_SHIFT
+ PAGE_SHIFT
@@
@@
- PAGE_CACHE_SIZE
+ PAGE_SIZE
@@
@@
- PAGE_CACHE_MASK
+ PAGE_MASK
@@
expression E;
@@
- PAGE_CACHE_ALIGN(E)
+ PAGE_ALIGN(E)
@@
expression E;
@@
- page_cache_get(E)
+ get_page(E)
@@
expression E;
@@
- page_cache_release(E)
+ put_page(E)
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-04-01 20:29:47 +08:00
|
|
|
xfs_vm_invalidatepage(page, 0, PAGE_SIZE);
|
2010-03-05 10:00:42 +08:00
|
|
|
}
|
|
|
|
|
2016-02-15 14:23:12 +08:00
|
|
|
/*
|
|
|
|
* We implement an immediate ioend submission policy here to avoid needing to
|
|
|
|
* chain multiple ioends and hence nest mempool allocations which can violate
|
|
|
|
* forward progress guarantees we need to provide. The current ioend we are
|
2018-07-12 13:26:05 +08:00
|
|
|
* adding blocks to is cached on the writepage context, and if the new block
|
2016-02-15 14:23:12 +08:00
|
|
|
* does not append to the cached ioend it will create a new ioend and cache that
|
|
|
|
* instead.
|
|
|
|
*
|
|
|
|
* If a new ioend is created and cached, the old ioend is returned and queued
|
|
|
|
* locally for submission once the entire page is processed or an error has been
|
|
|
|
* detected. While ioends are submitted immediately after they are completed,
|
|
|
|
* batching optimisations are provided by higher level block plugging.
|
|
|
|
*
|
|
|
|
* At the end of a writeback pass, there will be a cached ioend remaining on the
|
|
|
|
* writepage context that the caller will need to submit.
|
|
|
|
*/
|
2016-02-15 14:21:37 +08:00
|
|
|
static int
|
|
|
|
xfs_writepage_map(
|
|
|
|
struct xfs_writepage_ctx *wpc,
|
2016-02-15 14:23:12 +08:00
|
|
|
struct writeback_control *wbc,
|
2016-02-15 14:21:37 +08:00
|
|
|
struct inode *inode,
|
|
|
|
struct page *page,
|
2017-11-28 01:50:22 +08:00
|
|
|
uint64_t end_offset)
|
2016-02-15 14:21:37 +08:00
|
|
|
{
|
2016-02-15 14:23:12 +08:00
|
|
|
LIST_HEAD(submit_list);
|
2018-07-12 13:26:05 +08:00
|
|
|
struct iomap_page *iop = to_iomap_page(page);
|
|
|
|
unsigned len = i_blocksize(inode);
|
2016-02-15 14:23:12 +08:00
|
|
|
struct xfs_ioend *ioend, *next;
|
2018-07-12 13:26:00 +08:00
|
|
|
uint64_t file_offset; /* file offset of page */
|
2018-07-12 13:26:05 +08:00
|
|
|
int error = 0, count = 0, i;
|
2016-02-15 14:21:37 +08:00
|
|
|
|
2018-07-12 13:26:05 +08:00
|
|
|
ASSERT(iop || i_blocksize(inode) == PAGE_SIZE);
|
|
|
|
ASSERT(!iop || atomic_read(&iop->write_count) == 0);
|
2018-07-12 13:26:04 +08:00
|
|
|
|
xfs: make xfs_writepage_map extent map centric
xfs_writepage_map() iterates over the bufferheads on a page to decide
what sort of IO to do and what actions to take. However, when it comes
to reflink and deciding when it needs to execute a COW operation, we no
longer look at the bufferhead state but instead we ignore than and look
up internal state held in the COW fork extent list.
This means xfs_writepage_map() is somewhat confused. It does stuff, then
ignores it, then tries to handle the impedence mismatch by shovelling the
results inside the existing mapping code. It works, but it's a bit of a
mess and it makes it hard to fix the cached map bug that the writepage
code currently has.
To unify the two different mechanisms, we first have to choose a direction.
That's already been set - we're de-emphasising bufferheads so they are no
longer a control structure as we need to do taht to allow for eventual
removal. Hence we need to move away from looking at bufferhead state to
determine what operations we need to perform.
We can't completely get rid of bufferheads yet - they do contain some
state that is absolutely necessary, such as whether that part of the page
contains valid data or not (buffer_uptodate()). Other state in the
bufferhead is redundant:
BH_dirty - the page is dirty, so we can ignore this and just
write it
BH_delay - we have delalloc extent info in the DATA fork extent
tree
BH_unwritten - same as BH_delay
BH_mapped - indicates we've already used it once for IO and it is
mapped to a disk address. Needs to be ignored for COW
blocks.
The BH_mapped flag is an interesting case - it's supposed to indicate that
it's already mapped to disk and so we can just use it "as is". In theory,
we don't even have to do an extent lookup to find where to write it too,
but we have to do that anyway to determine we are actually writing over a
valid extent. Hence it's not even serving the purpose of avoiding a an
extent lookup during writeback, and so we can pretty much ignore it.
Especially as we have to ignore it for COW operations...
Therefore, use the extent map as the source of information to tell us
what actions we need to take and what sort of IO we should perform. The
first step is to have xfs_map_blocks() set the io type according to what
it looks up. This means it can easily handle both normal overwrite and
COW cases. The only thing we also need to add is the ability to return
hole mappings.
We need to return and cache hole mappings now for the case of multiple
blocks per page. We no longer use the BH_mapped to indicate a block over
a hole, so we have to get that info from xfs_map_blocks(). We cache it so
that holes that span two pages don't need separate lookups. This allows us
to avoid ever doing write IO over a hole, too.
Now that we have xfs_map_blocks() returning both a cached map and the type
of IO we need to perform, we can rewrite xfs_writepage_map() to drop all
the bufferhead control. It's also much simplified because it doesn't need
to explicitly handle COW operations. Instead of iterating bufferheads, it
iterates blocks within the page and then looks up what per-block state is
required from the appropriate bufferhead. It then validates the cached
map, and if it's not valid, we get a new map. If we don't get a valid map
or it's over a hole, we skip the block.
At this point, we have to remap the bufferhead via xfs_map_at_offset().
As previously noted, we had to do this even if the buffer was already
mapped as the mapping would be stale for XFS_IO_DELALLOC, XFS_IO_UNWRITTEN
and XFS_IO_COW IO types. With xfs_map_blocks() now controlling the type,
even XFS_IO_OVERWRITE types need remapping, as converted-but-not-yet-
written delalloc extents beyond EOF can be reported at XFS_IO_OVERWRITE.
Bufferheads that span such regions still need their BH_Delay flags cleared
and their block numbers calculated, so we now unconditionally map each
bufferhead before submission.
But wait! There's more - remember the old "treat unwritten extents as
holes on read" hack? Yeah, that means we can have a dirty page with
unmapped, unwritten bufferheads that contain data! What makes these so
special is that the unwritten "hole" bufferheads do not have a valid block
device pointer, so if we attempt to write them xfs_add_to_ioend() blows
up. So we make xfs_map_at_offset() do the "realtime or data device"
lookup from the inode and ignore what was or wasn't put into the
bufferhead when the buffer was instantiated.
The astute reader will have realised by now that this code treats
unwritten extents in multiple-blocks-per-page situations differently.
If we get any combination of unwritten blocks on a dirty page that contain
valid data in the page, we're going to convert them to real extents. This
can actually be a win, because it means that pages with interleaving
unwritten and written blocks will get converted to a single written extent
with zeros replacing the interspersed unwritten blocks. This is actually
good for reducing extent list and conversion overhead, and it means we
issue a contiguous IO instead of lots of little ones. The downside is
that we use up a little extra IO bandwidth. Neither of these seem like a
bad thing given that spinning disks are seek sensitive, and SSDs/pmem have
bandwidth to burn and the lower Io latency/CPU overhead of fewer, larger
IOs will result in better performance on them...
As a result of all this, the only state we actually care about from the
bufferhead is a single flag - BH_Uptodate. We still use the bufferhead to
pass some information to the bio via xfs_add_to_ioend(), but that is
trivial to separate and pass explicitly. This means we really only need
1 bit of state per block per page from the buffered write path in the
writeback path. Everything else we do with the bufferhead is purely to
make the buffered IO front end continue to work correctly. i.e we've
pretty much marginalised bufferheads in the writeback path completely.
Signed-off-By: Dave Chinner <dchinner@redhat.com>
[hch: forward port, refactor and split off bits into other commits]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
2018-07-12 13:26:00 +08:00
|
|
|
/*
|
2018-07-12 13:26:05 +08:00
|
|
|
* Walk through the page to find areas to write back. If we run off the
|
|
|
|
* end of the current map or find the current map invalid, grab a new
|
|
|
|
* one.
|
xfs: make xfs_writepage_map extent map centric
xfs_writepage_map() iterates over the bufferheads on a page to decide
what sort of IO to do and what actions to take. However, when it comes
to reflink and deciding when it needs to execute a COW operation, we no
longer look at the bufferhead state but instead we ignore than and look
up internal state held in the COW fork extent list.
This means xfs_writepage_map() is somewhat confused. It does stuff, then
ignores it, then tries to handle the impedence mismatch by shovelling the
results inside the existing mapping code. It works, but it's a bit of a
mess and it makes it hard to fix the cached map bug that the writepage
code currently has.
To unify the two different mechanisms, we first have to choose a direction.
That's already been set - we're de-emphasising bufferheads so they are no
longer a control structure as we need to do taht to allow for eventual
removal. Hence we need to move away from looking at bufferhead state to
determine what operations we need to perform.
We can't completely get rid of bufferheads yet - they do contain some
state that is absolutely necessary, such as whether that part of the page
contains valid data or not (buffer_uptodate()). Other state in the
bufferhead is redundant:
BH_dirty - the page is dirty, so we can ignore this and just
write it
BH_delay - we have delalloc extent info in the DATA fork extent
tree
BH_unwritten - same as BH_delay
BH_mapped - indicates we've already used it once for IO and it is
mapped to a disk address. Needs to be ignored for COW
blocks.
The BH_mapped flag is an interesting case - it's supposed to indicate that
it's already mapped to disk and so we can just use it "as is". In theory,
we don't even have to do an extent lookup to find where to write it too,
but we have to do that anyway to determine we are actually writing over a
valid extent. Hence it's not even serving the purpose of avoiding a an
extent lookup during writeback, and so we can pretty much ignore it.
Especially as we have to ignore it for COW operations...
Therefore, use the extent map as the source of information to tell us
what actions we need to take and what sort of IO we should perform. The
first step is to have xfs_map_blocks() set the io type according to what
it looks up. This means it can easily handle both normal overwrite and
COW cases. The only thing we also need to add is the ability to return
hole mappings.
We need to return and cache hole mappings now for the case of multiple
blocks per page. We no longer use the BH_mapped to indicate a block over
a hole, so we have to get that info from xfs_map_blocks(). We cache it so
that holes that span two pages don't need separate lookups. This allows us
to avoid ever doing write IO over a hole, too.
Now that we have xfs_map_blocks() returning both a cached map and the type
of IO we need to perform, we can rewrite xfs_writepage_map() to drop all
the bufferhead control. It's also much simplified because it doesn't need
to explicitly handle COW operations. Instead of iterating bufferheads, it
iterates blocks within the page and then looks up what per-block state is
required from the appropriate bufferhead. It then validates the cached
map, and if it's not valid, we get a new map. If we don't get a valid map
or it's over a hole, we skip the block.
At this point, we have to remap the bufferhead via xfs_map_at_offset().
As previously noted, we had to do this even if the buffer was already
mapped as the mapping would be stale for XFS_IO_DELALLOC, XFS_IO_UNWRITTEN
and XFS_IO_COW IO types. With xfs_map_blocks() now controlling the type,
even XFS_IO_OVERWRITE types need remapping, as converted-but-not-yet-
written delalloc extents beyond EOF can be reported at XFS_IO_OVERWRITE.
Bufferheads that span such regions still need their BH_Delay flags cleared
and their block numbers calculated, so we now unconditionally map each
bufferhead before submission.
But wait! There's more - remember the old "treat unwritten extents as
holes on read" hack? Yeah, that means we can have a dirty page with
unmapped, unwritten bufferheads that contain data! What makes these so
special is that the unwritten "hole" bufferheads do not have a valid block
device pointer, so if we attempt to write them xfs_add_to_ioend() blows
up. So we make xfs_map_at_offset() do the "realtime or data device"
lookup from the inode and ignore what was or wasn't put into the
bufferhead when the buffer was instantiated.
The astute reader will have realised by now that this code treats
unwritten extents in multiple-blocks-per-page situations differently.
If we get any combination of unwritten blocks on a dirty page that contain
valid data in the page, we're going to convert them to real extents. This
can actually be a win, because it means that pages with interleaving
unwritten and written blocks will get converted to a single written extent
with zeros replacing the interspersed unwritten blocks. This is actually
good for reducing extent list and conversion overhead, and it means we
issue a contiguous IO instead of lots of little ones. The downside is
that we use up a little extra IO bandwidth. Neither of these seem like a
bad thing given that spinning disks are seek sensitive, and SSDs/pmem have
bandwidth to burn and the lower Io latency/CPU overhead of fewer, larger
IOs will result in better performance on them...
As a result of all this, the only state we actually care about from the
bufferhead is a single flag - BH_Uptodate. We still use the bufferhead to
pass some information to the bio via xfs_add_to_ioend(), but that is
trivial to separate and pass explicitly. This means we really only need
1 bit of state per block per page from the buffered write path in the
writeback path. Everything else we do with the bufferhead is purely to
make the buffered IO front end continue to work correctly. i.e we've
pretty much marginalised bufferheads in the writeback path completely.
Signed-off-By: Dave Chinner <dchinner@redhat.com>
[hch: forward port, refactor and split off bits into other commits]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
2018-07-12 13:26:00 +08:00
|
|
|
*/
|
2018-07-12 13:26:05 +08:00
|
|
|
for (i = 0, file_offset = page_offset(page);
|
|
|
|
i < (PAGE_SIZE >> inode->i_blkbits) && file_offset < end_offset;
|
|
|
|
i++, file_offset += len) {
|
|
|
|
if (iop && !test_bit(i, iop->uptodate))
|
2016-02-15 14:21:37 +08:00
|
|
|
continue;
|
|
|
|
|
2018-07-12 13:26:02 +08:00
|
|
|
error = xfs_map_blocks(wpc, inode, file_offset);
|
|
|
|
if (error)
|
|
|
|
break;
|
2018-07-12 13:26:05 +08:00
|
|
|
if (wpc->io_type == XFS_IO_HOLE)
|
2018-07-12 13:25:59 +08:00
|
|
|
continue;
|
2018-07-12 13:26:05 +08:00
|
|
|
xfs_add_to_ioend(inode, file_offset, page, iop, wpc, wbc,
|
|
|
|
&submit_list);
|
2018-07-12 13:25:59 +08:00
|
|
|
count++;
|
xfs: make xfs_writepage_map extent map centric
xfs_writepage_map() iterates over the bufferheads on a page to decide
what sort of IO to do and what actions to take. However, when it comes
to reflink and deciding when it needs to execute a COW operation, we no
longer look at the bufferhead state but instead we ignore than and look
up internal state held in the COW fork extent list.
This means xfs_writepage_map() is somewhat confused. It does stuff, then
ignores it, then tries to handle the impedence mismatch by shovelling the
results inside the existing mapping code. It works, but it's a bit of a
mess and it makes it hard to fix the cached map bug that the writepage
code currently has.
To unify the two different mechanisms, we first have to choose a direction.
That's already been set - we're de-emphasising bufferheads so they are no
longer a control structure as we need to do taht to allow for eventual
removal. Hence we need to move away from looking at bufferhead state to
determine what operations we need to perform.
We can't completely get rid of bufferheads yet - they do contain some
state that is absolutely necessary, such as whether that part of the page
contains valid data or not (buffer_uptodate()). Other state in the
bufferhead is redundant:
BH_dirty - the page is dirty, so we can ignore this and just
write it
BH_delay - we have delalloc extent info in the DATA fork extent
tree
BH_unwritten - same as BH_delay
BH_mapped - indicates we've already used it once for IO and it is
mapped to a disk address. Needs to be ignored for COW
blocks.
The BH_mapped flag is an interesting case - it's supposed to indicate that
it's already mapped to disk and so we can just use it "as is". In theory,
we don't even have to do an extent lookup to find where to write it too,
but we have to do that anyway to determine we are actually writing over a
valid extent. Hence it's not even serving the purpose of avoiding a an
extent lookup during writeback, and so we can pretty much ignore it.
Especially as we have to ignore it for COW operations...
Therefore, use the extent map as the source of information to tell us
what actions we need to take and what sort of IO we should perform. The
first step is to have xfs_map_blocks() set the io type according to what
it looks up. This means it can easily handle both normal overwrite and
COW cases. The only thing we also need to add is the ability to return
hole mappings.
We need to return and cache hole mappings now for the case of multiple
blocks per page. We no longer use the BH_mapped to indicate a block over
a hole, so we have to get that info from xfs_map_blocks(). We cache it so
that holes that span two pages don't need separate lookups. This allows us
to avoid ever doing write IO over a hole, too.
Now that we have xfs_map_blocks() returning both a cached map and the type
of IO we need to perform, we can rewrite xfs_writepage_map() to drop all
the bufferhead control. It's also much simplified because it doesn't need
to explicitly handle COW operations. Instead of iterating bufferheads, it
iterates blocks within the page and then looks up what per-block state is
required from the appropriate bufferhead. It then validates the cached
map, and if it's not valid, we get a new map. If we don't get a valid map
or it's over a hole, we skip the block.
At this point, we have to remap the bufferhead via xfs_map_at_offset().
As previously noted, we had to do this even if the buffer was already
mapped as the mapping would be stale for XFS_IO_DELALLOC, XFS_IO_UNWRITTEN
and XFS_IO_COW IO types. With xfs_map_blocks() now controlling the type,
even XFS_IO_OVERWRITE types need remapping, as converted-but-not-yet-
written delalloc extents beyond EOF can be reported at XFS_IO_OVERWRITE.
Bufferheads that span such regions still need their BH_Delay flags cleared
and their block numbers calculated, so we now unconditionally map each
bufferhead before submission.
But wait! There's more - remember the old "treat unwritten extents as
holes on read" hack? Yeah, that means we can have a dirty page with
unmapped, unwritten bufferheads that contain data! What makes these so
special is that the unwritten "hole" bufferheads do not have a valid block
device pointer, so if we attempt to write them xfs_add_to_ioend() blows
up. So we make xfs_map_at_offset() do the "realtime or data device"
lookup from the inode and ignore what was or wasn't put into the
bufferhead when the buffer was instantiated.
The astute reader will have realised by now that this code treats
unwritten extents in multiple-blocks-per-page situations differently.
If we get any combination of unwritten blocks on a dirty page that contain
valid data in the page, we're going to convert them to real extents. This
can actually be a win, because it means that pages with interleaving
unwritten and written blocks will get converted to a single written extent
with zeros replacing the interspersed unwritten blocks. This is actually
good for reducing extent list and conversion overhead, and it means we
issue a contiguous IO instead of lots of little ones. The downside is
that we use up a little extra IO bandwidth. Neither of these seem like a
bad thing given that spinning disks are seek sensitive, and SSDs/pmem have
bandwidth to burn and the lower Io latency/CPU overhead of fewer, larger
IOs will result in better performance on them...
As a result of all this, the only state we actually care about from the
bufferhead is a single flag - BH_Uptodate. We still use the bufferhead to
pass some information to the bio via xfs_add_to_ioend(), but that is
trivial to separate and pass explicitly. This means we really only need
1 bit of state per block per page from the buffered write path in the
writeback path. Everything else we do with the bufferhead is purely to
make the buffered IO front end continue to work correctly. i.e we've
pretty much marginalised bufferheads in the writeback path completely.
Signed-off-By: Dave Chinner <dchinner@redhat.com>
[hch: forward port, refactor and split off bits into other commits]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
2018-07-12 13:26:00 +08:00
|
|
|
}
|
2016-02-15 14:21:37 +08:00
|
|
|
|
2016-02-15 14:23:12 +08:00
|
|
|
ASSERT(wpc->ioend || list_empty(&submit_list));
|
2018-07-12 13:26:03 +08:00
|
|
|
ASSERT(PageLocked(page));
|
|
|
|
ASSERT(!PageWriteback(page));
|
2016-02-15 14:21:37 +08:00
|
|
|
|
|
|
|
/*
|
2018-07-12 13:26:05 +08:00
|
|
|
* On error, we have to fail the ioend here because we may have set
|
|
|
|
* pages under writeback, we have to make sure we run IO completion to
|
|
|
|
* mark the error state of the IO appropriately, so we can't cancel the
|
|
|
|
* ioend directly here. That means we have to mark this page as under
|
|
|
|
* writeback if we included any blocks from it in the ioend chain so
|
|
|
|
* that completion treats it correctly.
|
2016-02-15 14:21:37 +08:00
|
|
|
*
|
2016-02-15 14:23:12 +08:00
|
|
|
* If we didn't include the page in the ioend, the on error we can
|
|
|
|
* simply discard and unlock it as there are no other users of the page
|
2018-07-12 13:26:05 +08:00
|
|
|
* now. The caller will still need to trigger submission of outstanding
|
|
|
|
* ioends on the writepage context so they are treated correctly on
|
|
|
|
* error.
|
2016-02-15 14:21:37 +08:00
|
|
|
*/
|
2018-07-12 13:26:04 +08:00
|
|
|
if (unlikely(error)) {
|
|
|
|
if (!count) {
|
|
|
|
xfs_aops_discard_page(page);
|
|
|
|
ClearPageUptodate(page);
|
|
|
|
unlock_page(page);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2018-07-12 13:26:03 +08:00
|
|
|
/*
|
|
|
|
* If the page was not fully cleaned, we need to ensure that the
|
|
|
|
* higher layers come back to it correctly. That means we need
|
|
|
|
* to keep the page dirty, and for WB_SYNC_ALL writeback we need
|
|
|
|
* to ensure the PAGECACHE_TAG_TOWRITE index mark is not removed
|
|
|
|
* so another attempt to write this page in this writeback sweep
|
|
|
|
* will be made.
|
|
|
|
*/
|
2018-07-12 13:26:04 +08:00
|
|
|
set_page_writeback_keepwrite(page);
|
2016-02-15 14:23:12 +08:00
|
|
|
} else {
|
2018-07-12 13:26:03 +08:00
|
|
|
clear_page_dirty_for_io(page);
|
|
|
|
set_page_writeback(page);
|
2016-02-15 14:21:37 +08:00
|
|
|
}
|
2016-02-15 14:23:12 +08:00
|
|
|
|
2018-07-12 13:26:04 +08:00
|
|
|
unlock_page(page);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Preserve the original error if there was one, otherwise catch
|
|
|
|
* submission errors here and propagate into subsequent ioend
|
|
|
|
* submissions.
|
|
|
|
*/
|
|
|
|
list_for_each_entry_safe(ioend, next, &submit_list, io_list) {
|
|
|
|
int error2;
|
|
|
|
|
|
|
|
list_del_init(&ioend->io_list);
|
|
|
|
error2 = xfs_submit_ioend(wbc, ioend, error);
|
|
|
|
if (error2 && !error)
|
|
|
|
error = error2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2018-07-12 13:26:05 +08:00
|
|
|
* We can end up here with no error and nothing to write only if we race
|
|
|
|
* with a partial page truncate on a sub-page block sized filesystem.
|
2018-07-12 13:26:04 +08:00
|
|
|
*/
|
|
|
|
if (!count)
|
|
|
|
end_page_writeback(page);
|
|
|
|
done:
|
2016-02-15 14:21:37 +08:00
|
|
|
mapping_set_error(page->mapping, error);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
2010-06-24 07:45:48 +08:00
|
|
|
* Write out a dirty page.
|
|
|
|
*
|
|
|
|
* For delalloc space on the page we need to allocate space and flush it.
|
|
|
|
* For unwritten space on the page we need to start the conversion to
|
|
|
|
* regular allocated space.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
STATIC int
|
2016-02-15 14:21:19 +08:00
|
|
|
xfs_do_writepage(
|
2010-06-24 07:45:48 +08:00
|
|
|
struct page *page,
|
2016-02-15 14:21:19 +08:00
|
|
|
struct writeback_control *wbc,
|
|
|
|
void *data)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2016-02-15 14:21:19 +08:00
|
|
|
struct xfs_writepage_ctx *wpc = data;
|
2010-06-24 07:45:48 +08:00
|
|
|
struct inode *inode = page->mapping->host;
|
2005-04-17 06:20:36 +08:00
|
|
|
loff_t offset;
|
2017-06-17 02:00:05 +08:00
|
|
|
uint64_t end_offset;
|
2016-02-15 14:21:31 +08:00
|
|
|
pgoff_t end_index;
|
2010-06-24 07:45:48 +08:00
|
|
|
|
2013-05-22 11:58:01 +08:00
|
|
|
trace_xfs_writepage(inode, page, 0, 0);
|
2010-06-24 07:45:48 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Refuse to write the page out if we are called from reclaim context.
|
|
|
|
*
|
2010-06-28 22:34:44 +08:00
|
|
|
* This avoids stack overflows when called from deeply used stacks in
|
|
|
|
* random callers for direct reclaim or memcg reclaim. We explicitly
|
|
|
|
* allow reclaim from kswapd as the stack usage there is relatively low.
|
2010-06-24 07:45:48 +08:00
|
|
|
*
|
2011-11-01 08:07:45 +08:00
|
|
|
* This should never happen except in the case of a VM regression so
|
|
|
|
* warn about it.
|
2010-06-24 07:45:48 +08:00
|
|
|
*/
|
2011-11-01 08:07:45 +08:00
|
|
|
if (WARN_ON_ONCE((current->flags & (PF_MEMALLOC|PF_KSWAPD)) ==
|
|
|
|
PF_MEMALLOC))
|
2010-08-24 09:47:51 +08:00
|
|
|
goto redirty;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2010-06-24 07:45:48 +08:00
|
|
|
/*
|
2011-07-08 20:34:05 +08:00
|
|
|
* Given that we do not allow direct reclaim to call us, we should
|
|
|
|
* never be called while in a filesystem transaction.
|
2010-06-24 07:45:48 +08:00
|
|
|
*/
|
2017-05-04 05:53:12 +08:00
|
|
|
if (WARN_ON_ONCE(current->flags & PF_MEMALLOC_NOFS))
|
2010-08-24 09:47:51 +08:00
|
|
|
goto redirty;
|
2010-06-24 07:45:48 +08:00
|
|
|
|
2014-05-20 06:24:26 +08:00
|
|
|
/*
|
2016-02-15 14:21:31 +08:00
|
|
|
* Is this page beyond the end of the file?
|
|
|
|
*
|
2014-05-20 06:24:26 +08:00
|
|
|
* The page index is less than the end_index, adjust the end_offset
|
|
|
|
* to the highest offset that this page should represent.
|
|
|
|
* -----------------------------------------------------
|
|
|
|
* | file mapping | <EOF> |
|
|
|
|
* -----------------------------------------------------
|
|
|
|
* | Page ... | Page N-2 | Page N-1 | Page N | |
|
|
|
|
* ^--------------------------------^----------|--------
|
|
|
|
* | desired writeback range | see else |
|
|
|
|
* ---------------------------------^------------------|
|
|
|
|
*/
|
2016-02-15 14:21:31 +08:00
|
|
|
offset = i_size_read(inode);
|
mm, fs: get rid of PAGE_CACHE_* and page_cache_{get,release} macros
PAGE_CACHE_{SIZE,SHIFT,MASK,ALIGN} macros were introduced *long* time
ago with promise that one day it will be possible to implement page
cache with bigger chunks than PAGE_SIZE.
This promise never materialized. And unlikely will.
We have many places where PAGE_CACHE_SIZE assumed to be equal to
PAGE_SIZE. And it's constant source of confusion on whether
PAGE_CACHE_* or PAGE_* constant should be used in a particular case,
especially on the border between fs and mm.
Global switching to PAGE_CACHE_SIZE != PAGE_SIZE would cause to much
breakage to be doable.
Let's stop pretending that pages in page cache are special. They are
not.
The changes are pretty straight-forward:
- <foo> << (PAGE_CACHE_SHIFT - PAGE_SHIFT) -> <foo>;
- <foo> >> (PAGE_CACHE_SHIFT - PAGE_SHIFT) -> <foo>;
- PAGE_CACHE_{SIZE,SHIFT,MASK,ALIGN} -> PAGE_{SIZE,SHIFT,MASK,ALIGN};
- page_cache_get() -> get_page();
- page_cache_release() -> put_page();
This patch contains automated changes generated with coccinelle using
script below. For some reason, coccinelle doesn't patch header files.
I've called spatch for them manually.
The only adjustment after coccinelle is revert of changes to
PAGE_CAHCE_ALIGN definition: we are going to drop it later.
There are few places in the code where coccinelle didn't reach. I'll
fix them manually in a separate patch. Comments and documentation also
will be addressed with the separate patch.
virtual patch
@@
expression E;
@@
- E << (PAGE_CACHE_SHIFT - PAGE_SHIFT)
+ E
@@
expression E;
@@
- E >> (PAGE_CACHE_SHIFT - PAGE_SHIFT)
+ E
@@
@@
- PAGE_CACHE_SHIFT
+ PAGE_SHIFT
@@
@@
- PAGE_CACHE_SIZE
+ PAGE_SIZE
@@
@@
- PAGE_CACHE_MASK
+ PAGE_MASK
@@
expression E;
@@
- PAGE_CACHE_ALIGN(E)
+ PAGE_ALIGN(E)
@@
expression E;
@@
- page_cache_get(E)
+ get_page(E)
@@
expression E;
@@
- page_cache_release(E)
+ put_page(E)
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-04-01 20:29:47 +08:00
|
|
|
end_index = offset >> PAGE_SHIFT;
|
2014-05-20 06:24:26 +08:00
|
|
|
if (page->index < end_index)
|
mm, fs: get rid of PAGE_CACHE_* and page_cache_{get,release} macros
PAGE_CACHE_{SIZE,SHIFT,MASK,ALIGN} macros were introduced *long* time
ago with promise that one day it will be possible to implement page
cache with bigger chunks than PAGE_SIZE.
This promise never materialized. And unlikely will.
We have many places where PAGE_CACHE_SIZE assumed to be equal to
PAGE_SIZE. And it's constant source of confusion on whether
PAGE_CACHE_* or PAGE_* constant should be used in a particular case,
especially on the border between fs and mm.
Global switching to PAGE_CACHE_SIZE != PAGE_SIZE would cause to much
breakage to be doable.
Let's stop pretending that pages in page cache are special. They are
not.
The changes are pretty straight-forward:
- <foo> << (PAGE_CACHE_SHIFT - PAGE_SHIFT) -> <foo>;
- <foo> >> (PAGE_CACHE_SHIFT - PAGE_SHIFT) -> <foo>;
- PAGE_CACHE_{SIZE,SHIFT,MASK,ALIGN} -> PAGE_{SIZE,SHIFT,MASK,ALIGN};
- page_cache_get() -> get_page();
- page_cache_release() -> put_page();
This patch contains automated changes generated with coccinelle using
script below. For some reason, coccinelle doesn't patch header files.
I've called spatch for them manually.
The only adjustment after coccinelle is revert of changes to
PAGE_CAHCE_ALIGN definition: we are going to drop it later.
There are few places in the code where coccinelle didn't reach. I'll
fix them manually in a separate patch. Comments and documentation also
will be addressed with the separate patch.
virtual patch
@@
expression E;
@@
- E << (PAGE_CACHE_SHIFT - PAGE_SHIFT)
+ E
@@
expression E;
@@
- E >> (PAGE_CACHE_SHIFT - PAGE_SHIFT)
+ E
@@
@@
- PAGE_CACHE_SHIFT
+ PAGE_SHIFT
@@
@@
- PAGE_CACHE_SIZE
+ PAGE_SIZE
@@
@@
- PAGE_CACHE_MASK
+ PAGE_MASK
@@
expression E;
@@
- PAGE_CACHE_ALIGN(E)
+ PAGE_ALIGN(E)
@@
expression E;
@@
- page_cache_get(E)
+ get_page(E)
@@
expression E;
@@
- page_cache_release(E)
+ put_page(E)
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-04-01 20:29:47 +08:00
|
|
|
end_offset = (xfs_off_t)(page->index + 1) << PAGE_SHIFT;
|
2014-05-20 06:24:26 +08:00
|
|
|
else {
|
|
|
|
/*
|
|
|
|
* Check whether the page to write out is beyond or straddles
|
|
|
|
* i_size or not.
|
|
|
|
* -------------------------------------------------------
|
|
|
|
* | file mapping | <EOF> |
|
|
|
|
* -------------------------------------------------------
|
|
|
|
* | Page ... | Page N-2 | Page N-1 | Page N | Beyond |
|
|
|
|
* ^--------------------------------^-----------|---------
|
|
|
|
* | | Straddles |
|
|
|
|
* ---------------------------------^-----------|--------|
|
|
|
|
*/
|
mm, fs: get rid of PAGE_CACHE_* and page_cache_{get,release} macros
PAGE_CACHE_{SIZE,SHIFT,MASK,ALIGN} macros were introduced *long* time
ago with promise that one day it will be possible to implement page
cache with bigger chunks than PAGE_SIZE.
This promise never materialized. And unlikely will.
We have many places where PAGE_CACHE_SIZE assumed to be equal to
PAGE_SIZE. And it's constant source of confusion on whether
PAGE_CACHE_* or PAGE_* constant should be used in a particular case,
especially on the border between fs and mm.
Global switching to PAGE_CACHE_SIZE != PAGE_SIZE would cause to much
breakage to be doable.
Let's stop pretending that pages in page cache are special. They are
not.
The changes are pretty straight-forward:
- <foo> << (PAGE_CACHE_SHIFT - PAGE_SHIFT) -> <foo>;
- <foo> >> (PAGE_CACHE_SHIFT - PAGE_SHIFT) -> <foo>;
- PAGE_CACHE_{SIZE,SHIFT,MASK,ALIGN} -> PAGE_{SIZE,SHIFT,MASK,ALIGN};
- page_cache_get() -> get_page();
- page_cache_release() -> put_page();
This patch contains automated changes generated with coccinelle using
script below. For some reason, coccinelle doesn't patch header files.
I've called spatch for them manually.
The only adjustment after coccinelle is revert of changes to
PAGE_CAHCE_ALIGN definition: we are going to drop it later.
There are few places in the code where coccinelle didn't reach. I'll
fix them manually in a separate patch. Comments and documentation also
will be addressed with the separate patch.
virtual patch
@@
expression E;
@@
- E << (PAGE_CACHE_SHIFT - PAGE_SHIFT)
+ E
@@
expression E;
@@
- E >> (PAGE_CACHE_SHIFT - PAGE_SHIFT)
+ E
@@
@@
- PAGE_CACHE_SHIFT
+ PAGE_SHIFT
@@
@@
- PAGE_CACHE_SIZE
+ PAGE_SIZE
@@
@@
- PAGE_CACHE_MASK
+ PAGE_MASK
@@
expression E;
@@
- PAGE_CACHE_ALIGN(E)
+ PAGE_ALIGN(E)
@@
expression E;
@@
- page_cache_get(E)
+ get_page(E)
@@
expression E;
@@
- page_cache_release(E)
+ put_page(E)
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-04-01 20:29:47 +08:00
|
|
|
unsigned offset_into_page = offset & (PAGE_SIZE - 1);
|
2012-07-04 00:20:00 +08:00
|
|
|
|
|
|
|
/*
|
2013-03-14 21:30:54 +08:00
|
|
|
* Skip the page if it is fully outside i_size, e.g. due to a
|
|
|
|
* truncate operation that is in progress. We must redirty the
|
|
|
|
* page so that reclaim stops reclaiming it. Otherwise
|
|
|
|
* xfs_vm_releasepage() is called on it and gets confused.
|
2014-05-20 06:24:26 +08:00
|
|
|
*
|
|
|
|
* Note that the end_index is unsigned long, it would overflow
|
|
|
|
* if the given offset is greater than 16TB on 32-bit system
|
|
|
|
* and if we do check the page is fully outside i_size or not
|
|
|
|
* via "if (page->index >= end_index + 1)" as "end_index + 1"
|
|
|
|
* will be evaluated to 0. Hence this page will be redirtied
|
|
|
|
* and be written out repeatedly which would result in an
|
|
|
|
* infinite loop, the user program that perform this operation
|
|
|
|
* will hang. Instead, we can verify this situation by checking
|
|
|
|
* if the page to write is totally beyond the i_size or if it's
|
|
|
|
* offset is just equal to the EOF.
|
2012-07-04 00:20:00 +08:00
|
|
|
*/
|
2014-05-20 06:24:26 +08:00
|
|
|
if (page->index > end_index ||
|
|
|
|
(page->index == end_index && offset_into_page == 0))
|
2013-03-14 21:30:54 +08:00
|
|
|
goto redirty;
|
2012-07-04 00:20:00 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The page straddles i_size. It must be zeroed out on each
|
|
|
|
* and every writepage invocation because it may be mmapped.
|
|
|
|
* "A file is mapped in multiples of the page size. For a file
|
2014-05-20 06:24:26 +08:00
|
|
|
* that is not a multiple of the page size, the remaining
|
2012-07-04 00:20:00 +08:00
|
|
|
* memory is zeroed when mapped, and writes to that region are
|
|
|
|
* not written out to the file."
|
|
|
|
*/
|
mm, fs: get rid of PAGE_CACHE_* and page_cache_{get,release} macros
PAGE_CACHE_{SIZE,SHIFT,MASK,ALIGN} macros were introduced *long* time
ago with promise that one day it will be possible to implement page
cache with bigger chunks than PAGE_SIZE.
This promise never materialized. And unlikely will.
We have many places where PAGE_CACHE_SIZE assumed to be equal to
PAGE_SIZE. And it's constant source of confusion on whether
PAGE_CACHE_* or PAGE_* constant should be used in a particular case,
especially on the border between fs and mm.
Global switching to PAGE_CACHE_SIZE != PAGE_SIZE would cause to much
breakage to be doable.
Let's stop pretending that pages in page cache are special. They are
not.
The changes are pretty straight-forward:
- <foo> << (PAGE_CACHE_SHIFT - PAGE_SHIFT) -> <foo>;
- <foo> >> (PAGE_CACHE_SHIFT - PAGE_SHIFT) -> <foo>;
- PAGE_CACHE_{SIZE,SHIFT,MASK,ALIGN} -> PAGE_{SIZE,SHIFT,MASK,ALIGN};
- page_cache_get() -> get_page();
- page_cache_release() -> put_page();
This patch contains automated changes generated with coccinelle using
script below. For some reason, coccinelle doesn't patch header files.
I've called spatch for them manually.
The only adjustment after coccinelle is revert of changes to
PAGE_CAHCE_ALIGN definition: we are going to drop it later.
There are few places in the code where coccinelle didn't reach. I'll
fix them manually in a separate patch. Comments and documentation also
will be addressed with the separate patch.
virtual patch
@@
expression E;
@@
- E << (PAGE_CACHE_SHIFT - PAGE_SHIFT)
+ E
@@
expression E;
@@
- E >> (PAGE_CACHE_SHIFT - PAGE_SHIFT)
+ E
@@
@@
- PAGE_CACHE_SHIFT
+ PAGE_SHIFT
@@
@@
- PAGE_CACHE_SIZE
+ PAGE_SIZE
@@
@@
- PAGE_CACHE_MASK
+ PAGE_MASK
@@
expression E;
@@
- PAGE_CACHE_ALIGN(E)
+ PAGE_ALIGN(E)
@@
expression E;
@@
- page_cache_get(E)
+ get_page(E)
@@
expression E;
@@
- page_cache_release(E)
+ put_page(E)
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-04-01 20:29:47 +08:00
|
|
|
zero_user_segment(page, offset_into_page, PAGE_SIZE);
|
2014-05-20 06:24:26 +08:00
|
|
|
|
|
|
|
/* Adjust the end_offset to the end of file */
|
|
|
|
end_offset = offset;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2017-11-28 01:50:22 +08:00
|
|
|
return xfs_writepage_map(wpc, wbc, inode, page, end_offset);
|
2006-03-14 10:26:27 +08:00
|
|
|
|
2010-08-24 09:47:51 +08:00
|
|
|
redirty:
|
2006-03-14 10:26:27 +08:00
|
|
|
redirty_page_for_writepage(wbc, page);
|
|
|
|
unlock_page(page);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-02-15 14:21:19 +08:00
|
|
|
STATIC int
|
|
|
|
xfs_vm_writepage(
|
|
|
|
struct page *page,
|
|
|
|
struct writeback_control *wbc)
|
|
|
|
{
|
|
|
|
struct xfs_writepage_ctx wpc = {
|
|
|
|
.io_type = XFS_IO_INVALID,
|
|
|
|
};
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = xfs_do_writepage(page, wbc, &wpc);
|
2016-02-15 14:23:12 +08:00
|
|
|
if (wpc.ioend)
|
|
|
|
ret = xfs_submit_ioend(wbc, wpc.ioend, ret);
|
|
|
|
return ret;
|
2016-02-15 14:21:19 +08:00
|
|
|
}
|
|
|
|
|
2006-06-09 13:27:16 +08:00
|
|
|
STATIC int
|
|
|
|
xfs_vm_writepages(
|
|
|
|
struct address_space *mapping,
|
|
|
|
struct writeback_control *wbc)
|
|
|
|
{
|
2016-02-15 14:21:19 +08:00
|
|
|
struct xfs_writepage_ctx wpc = {
|
|
|
|
.io_type = XFS_IO_INVALID,
|
|
|
|
};
|
|
|
|
int ret;
|
|
|
|
|
2007-08-29 09:44:37 +08:00
|
|
|
xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED);
|
2016-02-15 14:21:19 +08:00
|
|
|
ret = write_cache_pages(mapping, wbc, xfs_do_writepage, &wpc);
|
2016-02-15 14:23:12 +08:00
|
|
|
if (wpc.ioend)
|
|
|
|
ret = xfs_submit_ioend(wbc, wpc.ioend, ret);
|
|
|
|
return ret;
|
2006-06-09 13:27:16 +08:00
|
|
|
}
|
|
|
|
|
2018-03-08 07:26:44 +08:00
|
|
|
STATIC int
|
|
|
|
xfs_dax_writepages(
|
|
|
|
struct address_space *mapping,
|
|
|
|
struct writeback_control *wbc)
|
|
|
|
{
|
|
|
|
xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED);
|
|
|
|
return dax_writeback_mapping_range(mapping,
|
|
|
|
xfs_find_bdev_for_inode(mapping->host), wbc);
|
|
|
|
}
|
|
|
|
|
2006-03-14 10:26:27 +08:00
|
|
|
STATIC int
|
2006-03-17 14:26:25 +08:00
|
|
|
xfs_vm_releasepage(
|
2006-03-14 10:26:27 +08:00
|
|
|
struct page *page,
|
|
|
|
gfp_t gfp_mask)
|
|
|
|
{
|
2013-05-22 11:58:01 +08:00
|
|
|
trace_xfs_releasepage(page->mapping->host, page, 0, 0);
|
2018-07-12 13:26:05 +08:00
|
|
|
return iomap_releasepage(page, gfp_mask);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
STATIC sector_t
|
2006-03-14 10:54:26 +08:00
|
|
|
xfs_vm_bmap(
|
2005-04-17 06:20:36 +08:00
|
|
|
struct address_space *mapping,
|
|
|
|
sector_t block)
|
|
|
|
{
|
2018-06-02 00:03:09 +08:00
|
|
|
struct xfs_inode *ip = XFS_I(mapping->host);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2018-06-02 00:03:09 +08:00
|
|
|
trace_xfs_vm_bmap(ip);
|
2016-10-04 00:11:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The swap code (ab-)uses ->bmap to get a block mapping and then
|
2018-02-28 16:39:48 +08:00
|
|
|
* bypasses the file system for actual I/O. We really can't allow
|
2016-10-04 00:11:36 +08:00
|
|
|
* that on reflinks inodes, so we have to skip out here. And yes,
|
2017-06-22 11:27:35 +08:00
|
|
|
* 0 is the magic code for a bmap error.
|
|
|
|
*
|
|
|
|
* Since we don't pass back blockdev info, we can't return bmap
|
|
|
|
* information for rt files either.
|
2016-10-04 00:11:36 +08:00
|
|
|
*/
|
2017-06-22 11:27:35 +08:00
|
|
|
if (xfs_is_reflink_inode(ip) || XFS_IS_REALTIME_INODE(ip))
|
2016-10-04 00:11:36 +08:00
|
|
|
return 0;
|
2018-06-02 00:03:09 +08:00
|
|
|
return iomap_bmap(mapping, block, &xfs_iomap_ops);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
STATIC int
|
2006-03-14 10:54:26 +08:00
|
|
|
xfs_vm_readpage(
|
2005-04-17 06:20:36 +08:00
|
|
|
struct file *unused,
|
|
|
|
struct page *page)
|
|
|
|
{
|
2016-01-08 08:28:35 +08:00
|
|
|
trace_xfs_vm_readpage(page->mapping->host, 1);
|
2018-07-12 13:26:05 +08:00
|
|
|
return iomap_readpage(page, &xfs_iomap_ops);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
STATIC int
|
2006-03-14 10:54:26 +08:00
|
|
|
xfs_vm_readpages(
|
2005-04-17 06:20:36 +08:00
|
|
|
struct file *unused,
|
|
|
|
struct address_space *mapping,
|
|
|
|
struct list_head *pages,
|
|
|
|
unsigned nr_pages)
|
|
|
|
{
|
2016-01-08 08:28:35 +08:00
|
|
|
trace_xfs_vm_readpages(mapping->host, nr_pages);
|
2018-07-12 13:26:05 +08:00
|
|
|
return iomap_readpages(mapping, pages, nr_pages, &xfs_iomap_ops);
|
xfs: don't dirty buffers beyond EOF
generic/263 is failing fsx at this point with a page spanning
EOF that cannot be invalidated. The operations are:
1190 mapwrite 0x52c00 thru 0x5e569 (0xb96a bytes)
1191 mapread 0x5c000 thru 0x5d636 (0x1637 bytes)
1192 write 0x5b600 thru 0x771ff (0x1bc00 bytes)
where 1190 extents EOF from 0x54000 to 0x5e569. When the direct IO
write attempts to invalidate the cached page over this range, it
fails with -EBUSY and so any attempt to do page invalidation fails.
The real question is this: Why can't that page be invalidated after
it has been written to disk and cleaned?
Well, there's data on the first two buffers in the page (1k block
size, 4k page), but the third buffer on the page (i.e. beyond EOF)
is failing drop_buffers because it's bh->b_state == 0x3, which is
BH_Uptodate | BH_Dirty. IOWs, there's dirty buffers beyond EOF. Say
what?
OK, set_buffer_dirty() is called on all buffers from
__set_page_buffers_dirty(), regardless of whether the buffer is
beyond EOF or not, which means that when we get to ->writepage,
we have buffers marked dirty beyond EOF that we need to clean.
So, we need to implement our own .set_page_dirty method that
doesn't dirty buffers beyond EOF.
This is messy because the buffer code is not meant to be shared
and it has interesting locking issues on the buffer dirty bits.
So just copy and paste it and then modify it to suit what we need.
Note: the solutions the other filesystems and generic block code use
of marking the buffers clean in ->writepage does not work for XFS.
It still leaves dirty buffers beyond EOF and invalidations still
fail. Hence rather than play whack-a-mole, this patch simply
prevents those buffers from being dirtied in the first place.
cc: <stable@kernel.org>
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
2014-09-02 10:12:51 +08:00
|
|
|
}
|
|
|
|
|
2018-05-10 23:38:15 +08:00
|
|
|
static int
|
|
|
|
xfs_iomap_swapfile_activate(
|
|
|
|
struct swap_info_struct *sis,
|
|
|
|
struct file *swap_file,
|
|
|
|
sector_t *span)
|
|
|
|
{
|
|
|
|
sis->bdev = xfs_find_bdev_for_inode(file_inode(swap_file));
|
|
|
|
return iomap_swapfile_activate(sis, swap_file, span, &xfs_iomap_ops);
|
|
|
|
}
|
|
|
|
|
2006-06-28 19:26:44 +08:00
|
|
|
const struct address_space_operations xfs_address_space_operations = {
|
2006-03-14 10:54:26 +08:00
|
|
|
.readpage = xfs_vm_readpage,
|
|
|
|
.readpages = xfs_vm_readpages,
|
|
|
|
.writepage = xfs_vm_writepage,
|
2006-06-09 13:27:16 +08:00
|
|
|
.writepages = xfs_vm_writepages,
|
2018-07-12 13:26:05 +08:00
|
|
|
.set_page_dirty = iomap_set_page_dirty,
|
2006-03-17 14:26:25 +08:00
|
|
|
.releasepage = xfs_vm_releasepage,
|
|
|
|
.invalidatepage = xfs_vm_invalidatepage,
|
2006-03-14 10:54:26 +08:00
|
|
|
.bmap = xfs_vm_bmap,
|
2018-03-08 07:26:44 +08:00
|
|
|
.direct_IO = noop_direct_IO,
|
2018-07-12 13:26:05 +08:00
|
|
|
.migratepage = iomap_migrate_page,
|
|
|
|
.is_partially_uptodate = iomap_is_partially_uptodate,
|
2009-09-16 17:50:16 +08:00
|
|
|
.error_remove_page = generic_error_remove_page,
|
2018-05-10 23:38:15 +08:00
|
|
|
.swap_activate = xfs_iomap_swapfile_activate,
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
2018-03-08 07:26:44 +08:00
|
|
|
|
|
|
|
const struct address_space_operations xfs_dax_aops = {
|
|
|
|
.writepages = xfs_dax_writepages,
|
|
|
|
.direct_IO = noop_direct_IO,
|
|
|
|
.set_page_dirty = noop_set_page_dirty,
|
|
|
|
.invalidatepage = noop_invalidatepage,
|
2018-05-10 23:38:15 +08:00
|
|
|
.swap_activate = xfs_iomap_swapfile_activate,
|
2018-03-08 07:26:44 +08:00
|
|
|
};
|