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
|
|
|
|
*
|
2005-11-02 11:58:39 +08:00
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
2005-04-17 06:20:36 +08:00
|
|
|
|
* published by the Free Software Foundation.
|
|
|
|
|
*
|
2005-11-02 11:58:39 +08:00
|
|
|
|
* This program is distributed in the hope that it would be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
2005-04-17 06:20:36 +08:00
|
|
|
|
*
|
2005-11-02 11:58:39 +08:00
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write the Free Software Foundation,
|
|
|
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
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"
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 16:04:11 +08:00
|
|
|
|
#include <linux/gfp.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
|
#include <linux/mpage.h>
|
2006-01-11 17:48:14 +08:00
|
|
|
|
#include <linux/pagevec.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;
|
|
|
|
|
bool imap_valid;
|
|
|
|
|
unsigned int io_type;
|
|
|
|
|
struct xfs_ioend *ioend;
|
|
|
|
|
sector_t last_block;
|
|
|
|
|
};
|
|
|
|
|
|
2009-12-15 07:14:59 +08:00
|
|
|
|
void
|
2006-03-14 10:26:27 +08:00
|
|
|
|
xfs_count_page_state(
|
|
|
|
|
struct page *page,
|
|
|
|
|
int *delalloc,
|
|
|
|
|
int *unwritten)
|
|
|
|
|
{
|
|
|
|
|
struct buffer_head *bh, *head;
|
|
|
|
|
|
2010-06-24 07:46:01 +08:00
|
|
|
|
*delalloc = *unwritten = 0;
|
2006-03-14 10:26:27 +08:00
|
|
|
|
|
|
|
|
|
bh = head = page_buffers(page);
|
|
|
|
|
do {
|
2010-06-24 07:46:01 +08:00
|
|
|
|
if (buffer_unwritten(bh))
|
2006-03-14 10:26:27 +08:00
|
|
|
|
(*unwritten) = 1;
|
|
|
|
|
else if (buffer_delay(bh))
|
|
|
|
|
(*delalloc) = 1;
|
|
|
|
|
} while ((bh = bh->b_this_page) != head);
|
|
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-11 12:40:13 +08:00
|
|
|
|
/*
|
2016-04-06 06:12:28 +08:00
|
|
|
|
* We're now finished for good with this page. Update the page state via the
|
|
|
|
|
* associated buffer_heads, paying attention to the start and end offsets that
|
|
|
|
|
* we need to process on the page.
|
2016-07-22 07:56:38 +08:00
|
|
|
|
*
|
|
|
|
|
* Landmine Warning: bh->b_end_io() will call end_page_writeback() on the last
|
|
|
|
|
* buffer in the IO. Once it does this, it is unsafe to access the bufferhead or
|
|
|
|
|
* the page at all, as we may be racing with memory reclaim and it can free both
|
|
|
|
|
* the bufferhead chain and the page as it will see the page as clean and
|
|
|
|
|
* unused.
|
2016-04-06 06:12:28 +08:00
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
xfs_finish_page_writeback(
|
|
|
|
|
struct inode *inode,
|
|
|
|
|
struct bio_vec *bvec,
|
|
|
|
|
int error)
|
|
|
|
|
{
|
|
|
|
|
unsigned int end = bvec->bv_offset + bvec->bv_len - 1;
|
2016-07-22 07:56:38 +08:00
|
|
|
|
struct buffer_head *head, *bh, *next;
|
2016-04-06 06:12:28 +08:00
|
|
|
|
unsigned int off = 0;
|
2016-07-22 07:56:38 +08:00
|
|
|
|
unsigned int bsize;
|
2016-04-06 06:12:28 +08:00
|
|
|
|
|
|
|
|
|
ASSERT(bvec->bv_offset < PAGE_SIZE);
|
2017-02-28 06:28:32 +08:00
|
|
|
|
ASSERT((bvec->bv_offset & (i_blocksize(inode) - 1)) == 0);
|
2016-04-06 06:12:28 +08:00
|
|
|
|
ASSERT(end < PAGE_SIZE);
|
2017-02-28 06:28:32 +08:00
|
|
|
|
ASSERT((bvec->bv_len & (i_blocksize(inode) - 1)) == 0);
|
2016-04-06 06:12:28 +08:00
|
|
|
|
|
|
|
|
|
bh = head = page_buffers(bvec->bv_page);
|
|
|
|
|
|
2016-07-22 07:56:38 +08:00
|
|
|
|
bsize = bh->b_size;
|
2016-04-06 06:12:28 +08:00
|
|
|
|
do {
|
2016-07-22 07:56:38 +08:00
|
|
|
|
next = bh->b_this_page;
|
2016-04-06 06:12:28 +08:00
|
|
|
|
if (off < bvec->bv_offset)
|
|
|
|
|
goto next_bh;
|
|
|
|
|
if (off > end)
|
|
|
|
|
break;
|
|
|
|
|
bh->b_end_io(bh, !error);
|
|
|
|
|
next_bh:
|
2016-07-22 07:56:38 +08:00
|
|
|
|
off += bsize;
|
|
|
|
|
} while ((bh = next) != head);
|
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;
|
2016-04-06 06:34:30 +08:00
|
|
|
|
struct bio *last = ioend->io_bio;
|
2016-04-06 06:12:28 +08:00
|
|
|
|
struct bio *bio, *next;
|
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 */
|
|
|
|
|
bio_for_each_segment_all(bvec, bio, i)
|
|
|
|
|
xfs_finish_page_writeback(inode, bvec, error);
|
|
|
|
|
|
|
|
|
|
bio_put(bio);
|
2006-01-11 12:40:13 +08:00
|
|
|
|
}
|
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;
|
|
|
|
|
|
2016-04-06 07:19:55 +08:00
|
|
|
|
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0, 0, &tp);
|
|
|
|
|
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.
|
|
|
|
|
*/
|
|
|
|
|
current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
|
|
|
|
|
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.
|
|
|
|
|
*/
|
|
|
|
|
current_set_flags_nested(&tp->t_pflags, PF_FSTRANS);
|
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;
|
2016-04-06 06:34:30 +08:00
|
|
|
|
int error = ioend->io_bio->bi_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-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:
|
|
|
|
|
error = xfs_iomap_write_unwritten(ip, offset, size);
|
|
|
|
|
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
|
|
|
|
|
xfs_destroy_ioend(ioend, bio->bi_error);
|
2005-09-02 14:58:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
|
STATIC int
|
|
|
|
|
xfs_map_blocks(
|
|
|
|
|
struct inode *inode,
|
|
|
|
|
loff_t offset,
|
2010-04-28 20:28:56 +08:00
|
|
|
|
struct xfs_bmbt_irec *imap,
|
2016-02-15 14:20:50 +08:00
|
|
|
|
int type)
|
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);
|
2010-12-10 16:42:20 +08:00
|
|
|
|
xfs_fileoff_t offset_fsb, end_fsb;
|
|
|
|
|
int error = 0;
|
|
|
|
|
int bmapi_flags = XFS_BMAPI_ENTIRE;
|
|
|
|
|
int nimaps = 1;
|
|
|
|
|
|
|
|
|
|
if (XFS_FORCED_SHUTDOWN(mp))
|
2014-06-22 13:04:54 +08:00
|
|
|
|
return -EIO;
|
2010-12-10 16:42:20 +08:00
|
|
|
|
|
2016-10-04 00:11:34 +08:00
|
|
|
|
ASSERT(type != XFS_IO_COW);
|
2012-05-23 04:56:21 +08:00
|
|
|
|
if (type == XFS_IO_UNWRITTEN)
|
2010-12-10 16:42:20 +08:00
|
|
|
|
bmapi_flags |= XFS_BMAPI_IGSTATE;
|
2010-12-10 16:42:21 +08:00
|
|
|
|
|
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
|
|
|
|
|
2012-06-08 13:44:53 +08:00
|
|
|
|
if (offset + count > mp->m_super->s_maxbytes)
|
|
|
|
|
count = mp->m_super->s_maxbytes - offset;
|
2010-12-10 16:42:20 +08:00
|
|
|
|
end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
|
|
|
|
|
offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
2011-09-19 04:40:45 +08:00
|
|
|
|
error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
|
|
|
|
|
imap, &nimaps, bmapi_flags);
|
2016-10-04 00:11:34 +08:00
|
|
|
|
/*
|
|
|
|
|
* Truncate an overwrite extent if there's a pending CoW
|
|
|
|
|
* reservation before the end of this extent. This forces us
|
|
|
|
|
* to come back to writepage to take care of the CoW.
|
|
|
|
|
*/
|
|
|
|
|
if (nimaps && type == XFS_IO_OVERWRITE)
|
|
|
|
|
xfs_reflink_trim_irec_to_next_cow(ip, offset_fsb, imap);
|
2010-12-10 16:42:21 +08:00
|
|
|
|
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
2010-12-10 16:42:20 +08:00
|
|
|
|
|
2010-12-10 16:42:21 +08:00
|
|
|
|
if (error)
|
2014-06-25 12:58:08 +08:00
|
|
|
|
return error;
|
2010-12-10 16:42:20 +08:00
|
|
|
|
|
2012-05-23 04:56:21 +08:00
|
|
|
|
if (type == XFS_IO_DELALLOC &&
|
2010-12-10 16:42:21 +08:00
|
|
|
|
(!nimaps || isnullstartblock(imap->br_startblock))) {
|
2016-10-04 00:11:34 +08:00
|
|
|
|
error = xfs_iomap_write_allocate(ip, XFS_DATA_FORK, offset,
|
|
|
|
|
imap);
|
2010-12-10 16:42:20 +08:00
|
|
|
|
if (!error)
|
2016-10-04 00:11:34 +08:00
|
|
|
|
trace_xfs_map_blocks_alloc(ip, offset, count, type, imap);
|
2014-06-25 12:58:08 +08:00
|
|
|
|
return error;
|
2010-12-10 16:42:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
2010-12-10 16:42:21 +08:00
|
|
|
|
#ifdef DEBUG
|
2012-05-23 04:56:21 +08:00
|
|
|
|
if (type == XFS_IO_UNWRITTEN) {
|
2010-12-10 16:42:21 +08:00
|
|
|
|
ASSERT(nimaps);
|
|
|
|
|
ASSERT(imap->br_startblock != HOLESTARTBLOCK);
|
|
|
|
|
ASSERT(imap->br_startblock != DELAYSTARTBLOCK);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
if (nimaps)
|
|
|
|
|
trace_xfs_map_blocks_found(ip, offset, count, type, imap);
|
|
|
|
|
return 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-15 14:21:19 +08:00
|
|
|
|
STATIC bool
|
2010-04-28 20:28:58 +08:00
|
|
|
|
xfs_imap_valid(
|
2010-04-28 20:28:54 +08:00
|
|
|
|
struct inode *inode,
|
2010-04-28 20:28:56 +08:00
|
|
|
|
struct xfs_bmbt_irec *imap,
|
2010-04-28 20:28:58 +08:00
|
|
|
|
xfs_off_t offset)
|
2005-04-17 06:20:36 +08:00
|
|
|
|
{
|
2010-04-28 20:28:58 +08:00
|
|
|
|
offset >>= inode->i_blkbits;
|
2010-04-28 20:28:54 +08:00
|
|
|
|
|
2010-04-28 20:28:58 +08:00
|
|
|
|
return offset >= imap->br_startoff &&
|
|
|
|
|
offset < imap->br_startoff + imap->br_blockcount;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
2006-01-11 12:40:13 +08:00
|
|
|
|
STATIC void
|
|
|
|
|
xfs_start_buffer_writeback(
|
|
|
|
|
struct buffer_head *bh)
|
|
|
|
|
{
|
|
|
|
|
ASSERT(buffer_mapped(bh));
|
|
|
|
|
ASSERT(buffer_locked(bh));
|
|
|
|
|
ASSERT(!buffer_delay(bh));
|
|
|
|
|
ASSERT(!buffer_unwritten(bh));
|
|
|
|
|
|
|
|
|
|
mark_buffer_async_write(bh);
|
|
|
|
|
set_buffer_uptodate(bh);
|
|
|
|
|
clear_buffer_dirty(bh);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
STATIC void
|
|
|
|
|
xfs_start_page_writeback(
|
|
|
|
|
struct page *page,
|
2016-02-15 14:23:12 +08:00
|
|
|
|
int clear_dirty)
|
2006-01-11 12:40:13 +08:00
|
|
|
|
{
|
|
|
|
|
ASSERT(PageLocked(page));
|
|
|
|
|
ASSERT(!PageWriteback(page));
|
2014-09-23 13:36:27 +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.
|
|
|
|
|
*/
|
|
|
|
|
if (clear_dirty) {
|
2006-12-21 07:24:01 +08:00
|
|
|
|
clear_page_dirty_for_io(page);
|
2014-09-23 13:36:27 +08:00
|
|
|
|
set_page_writeback(page);
|
|
|
|
|
} else
|
|
|
|
|
set_page_writeback_keepwrite(page);
|
|
|
|
|
|
2006-01-11 12:40:13 +08:00
|
|
|
|
unlock_page(page);
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-07 18:11:09 +08:00
|
|
|
|
static inline int xfs_bio_add_buffer(struct bio *bio, struct buffer_head *bh)
|
2006-01-11 12:40:13 +08:00
|
|
|
|
{
|
|
|
|
|
return bio_add_page(bio, bh->b_page, bh->b_size, bh_offset(bh));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
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) {
|
|
|
|
|
status = xfs_reflink_convert_cow(XFS_I(ioend->io_inode),
|
|
|
|
|
ioend->io_offset, ioend->io_size);
|
|
|
|
|
}
|
|
|
|
|
|
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) {
|
2016-04-06 06:34:30 +08:00
|
|
|
|
ioend->io_bio->bi_error = status;
|
|
|
|
|
bio_endio(ioend->io_bio);
|
2016-02-15 14:23:12 +08:00
|
|
|
|
return status;
|
|
|
|
|
}
|
2006-01-18 10:38:12 +08:00
|
|
|
|
|
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 void
|
|
|
|
|
xfs_init_bio_from_bh(
|
|
|
|
|
struct bio *bio,
|
|
|
|
|
struct buffer_head *bh)
|
|
|
|
|
{
|
|
|
|
|
bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9);
|
|
|
|
|
bio->bi_bdev = bh->b_bdev;
|
|
|
|
|
}
|
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
|
|
|
|
|
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,
|
|
|
|
|
struct buffer_head *bh)
|
|
|
|
|
{
|
|
|
|
|
struct xfs_ioend *ioend;
|
|
|
|
|
struct bio *bio;
|
2006-01-11 12:40:13 +08:00
|
|
|
|
|
2016-04-06 06:34:30 +08:00
|
|
|
|
bio = bio_alloc_bioset(GFP_NOFS, BIO_MAX_PAGES, xfs_ioend_bioset);
|
|
|
|
|
xfs_init_bio_from_bh(bio, bh);
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
struct buffer_head *bh)
|
|
|
|
|
{
|
|
|
|
|
struct bio *new;
|
|
|
|
|
|
|
|
|
|
new = bio_alloc(GFP_NOFS, BIO_MAX_PAGES);
|
|
|
|
|
xfs_init_bio_from_bh(new, bh);
|
|
|
|
|
|
|
|
|
|
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);
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Test to see if we've been building up a completion structure for
|
|
|
|
|
* earlier buffers -- if so, we try to append to this ioend if we
|
|
|
|
|
* can, otherwise we finish off any current ioend and start another.
|
2016-02-15 14:23:12 +08:00
|
|
|
|
* Return the ioend we finished off so that the caller can submit it
|
|
|
|
|
* once it has finished processing the dirty page.
|
2006-01-11 12:40:13 +08:00
|
|
|
|
*/
|
|
|
|
|
STATIC void
|
|
|
|
|
xfs_add_to_ioend(
|
|
|
|
|
struct inode *inode,
|
|
|
|
|
struct buffer_head *bh,
|
2006-01-11 17:49:16 +08:00
|
|
|
|
xfs_off_t offset,
|
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
|
|
|
|
{
|
2016-02-15 14:21:19 +08:00
|
|
|
|
if (!wpc->ioend || wpc->io_type != wpc->ioend->io_type ||
|
2016-03-07 06:32:14 +08:00
|
|
|
|
bh->b_blocknr != wpc->last_block + 1 ||
|
|
|
|
|
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);
|
2016-04-06 06:34:30 +08:00
|
|
|
|
wpc->ioend = xfs_alloc_ioend(inode, wpc->io_type, offset, bh);
|
2006-01-11 12:40:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-06 06:34:30 +08:00
|
|
|
|
/*
|
|
|
|
|
* If the buffer doesn't fit into the bio we need to allocate a new
|
|
|
|
|
* one. This shouldn't happen more than once for a given buffer.
|
|
|
|
|
*/
|
|
|
|
|
while (xfs_bio_add_buffer(wpc->ioend->io_bio, bh) != bh->b_size)
|
|
|
|
|
xfs_chain_bio(wpc->ioend, wbc, bh);
|
2016-04-06 06:11:25 +08:00
|
|
|
|
|
2016-02-15 14:21:19 +08:00
|
|
|
|
wpc->ioend->io_size += bh->b_size;
|
|
|
|
|
wpc->last_block = bh->b_blocknr;
|
2016-02-15 14:23:12 +08:00
|
|
|
|
xfs_start_buffer_writeback(bh);
|
2006-01-11 12:40:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
2006-03-14 10:26:43 +08:00
|
|
|
|
STATIC void
|
|
|
|
|
xfs_map_buffer(
|
2010-04-28 20:28:52 +08:00
|
|
|
|
struct inode *inode,
|
2006-03-14 10:26:43 +08:00
|
|
|
|
struct buffer_head *bh,
|
2010-04-28 20:28:56 +08:00
|
|
|
|
struct xfs_bmbt_irec *imap,
|
2010-04-28 20:28:52 +08:00
|
|
|
|
xfs_off_t offset)
|
2006-03-14 10:26:43 +08:00
|
|
|
|
{
|
|
|
|
|
sector_t bn;
|
2010-04-28 20:28:54 +08:00
|
|
|
|
struct xfs_mount *m = XFS_I(inode)->i_mount;
|
2010-04-28 20:28:56 +08:00
|
|
|
|
xfs_off_t iomap_offset = XFS_FSB_TO_B(m, imap->br_startoff);
|
|
|
|
|
xfs_daddr_t iomap_bn = xfs_fsb_to_db(XFS_I(inode), imap->br_startblock);
|
2006-03-14 10:26:43 +08:00
|
|
|
|
|
2010-04-28 20:28:56 +08:00
|
|
|
|
ASSERT(imap->br_startblock != HOLESTARTBLOCK);
|
|
|
|
|
ASSERT(imap->br_startblock != DELAYSTARTBLOCK);
|
2006-03-14 10:26:43 +08:00
|
|
|
|
|
2010-04-28 20:28:55 +08:00
|
|
|
|
bn = (iomap_bn >> (inode->i_blkbits - BBSHIFT)) +
|
2010-04-28 20:28:54 +08:00
|
|
|
|
((offset - iomap_offset) >> inode->i_blkbits);
|
2006-03-14 10:26:43 +08:00
|
|
|
|
|
2010-04-28 20:28:52 +08:00
|
|
|
|
ASSERT(bn || XFS_IS_REALTIME_INODE(XFS_I(inode)));
|
2006-03-14 10:26:43 +08:00
|
|
|
|
|
|
|
|
|
bh->b_blocknr = bn;
|
|
|
|
|
set_buffer_mapped(bh);
|
|
|
|
|
}
|
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
|
STATIC void
|
|
|
|
|
xfs_map_at_offset(
|
2010-04-28 20:28:52 +08:00
|
|
|
|
struct inode *inode,
|
2005-04-17 06:20:36 +08:00
|
|
|
|
struct buffer_head *bh,
|
2010-04-28 20:28:56 +08:00
|
|
|
|
struct xfs_bmbt_irec *imap,
|
2010-04-28 20:28:52 +08:00
|
|
|
|
xfs_off_t offset)
|
2005-04-17 06:20:36 +08:00
|
|
|
|
{
|
2010-04-28 20:28:56 +08:00
|
|
|
|
ASSERT(imap->br_startblock != HOLESTARTBLOCK);
|
|
|
|
|
ASSERT(imap->br_startblock != DELAYSTARTBLOCK);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
2010-04-28 20:28:56 +08:00
|
|
|
|
xfs_map_buffer(inode, bh, imap, offset);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
set_buffer_mapped(bh);
|
|
|
|
|
clear_buffer_delay(bh);
|
2006-01-11 12:40:13 +08:00
|
|
|
|
clear_buffer_unwritten(bh);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2014-03-07 13:19:14 +08:00
|
|
|
|
* Test if a given page contains at least one buffer of a given @type.
|
|
|
|
|
* If @check_all_buffers is true, then we walk all the buffers in the page to
|
|
|
|
|
* try to find one of the type passed in. If it is not set, then the caller only
|
|
|
|
|
* needs to check the first buffer on the page for a match.
|
2005-04-17 06:20:36 +08:00
|
|
|
|
*/
|
2014-03-07 13:19:14 +08:00
|
|
|
|
STATIC bool
|
2012-04-23 13:58:43 +08:00
|
|
|
|
xfs_check_page_type(
|
2006-01-11 17:48:14 +08:00
|
|
|
|
struct page *page,
|
2014-03-07 13:19:14 +08:00
|
|
|
|
unsigned int type,
|
|
|
|
|
bool check_all_buffers)
|
2005-04-17 06:20:36 +08:00
|
|
|
|
{
|
2014-03-07 13:19:14 +08:00
|
|
|
|
struct buffer_head *bh;
|
|
|
|
|
struct buffer_head *head;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
2014-03-07 13:19:14 +08:00
|
|
|
|
if (PageWriteback(page))
|
|
|
|
|
return false;
|
|
|
|
|
if (!page->mapping)
|
|
|
|
|
return false;
|
|
|
|
|
if (!page_has_buffers(page))
|
|
|
|
|
return false;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
2014-03-07 13:19:14 +08:00
|
|
|
|
bh = head = page_buffers(page);
|
|
|
|
|
do {
|
|
|
|
|
if (buffer_unwritten(bh)) {
|
|
|
|
|
if (type == XFS_IO_UNWRITTEN)
|
|
|
|
|
return true;
|
|
|
|
|
} else if (buffer_delay(bh)) {
|
2014-04-04 03:56:30 +08:00
|
|
|
|
if (type == XFS_IO_DELALLOC)
|
2014-03-07 13:19:14 +08:00
|
|
|
|
return true;
|
|
|
|
|
} else if (buffer_dirty(bh) && buffer_mapped(bh)) {
|
2014-04-04 03:56:30 +08:00
|
|
|
|
if (type == XFS_IO_OVERWRITE)
|
2014-03-07 13:19:14 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
2014-03-07 13:19:14 +08:00
|
|
|
|
/* If we are only checking the first buffer, we are done now. */
|
|
|
|
|
if (!check_all_buffers)
|
|
|
|
|
break;
|
|
|
|
|
} while ((bh = bh->b_this_page) != head);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
2014-03-07 13:19:14 +08:00
|
|
|
|
return false;
|
2005-04-17 06:20:36 +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
|
|
|
|
{
|
2013-05-22 11:58:01 +08:00
|
|
|
|
trace_xfs_invalidatepage(page->mapping->host, page, offset,
|
|
|
|
|
length);
|
|
|
|
|
block_invalidatepage(page, offset, length);
|
2010-03-05 10:00:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If the page has delalloc buffers 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 a BUG() in xfs_get_blocks() later on if a direct IO read
|
|
|
|
|
* is done on that same region - the delalloc extent is returned when none is
|
|
|
|
|
* supposed to be there.
|
|
|
|
|
*
|
|
|
|
|
* We prevent this by truncating away the delalloc regions on the page before
|
|
|
|
|
* invalidating it. 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).
|
|
|
|
|
*
|
|
|
|
|
* This is not a performance critical path, so for now just do the punching a
|
|
|
|
|
* buffer head at a time.
|
|
|
|
|
*/
|
|
|
|
|
STATIC void
|
|
|
|
|
xfs_aops_discard_page(
|
|
|
|
|
struct page *page)
|
|
|
|
|
{
|
|
|
|
|
struct inode *inode = page->mapping->host;
|
|
|
|
|
struct xfs_inode *ip = XFS_I(inode);
|
|
|
|
|
struct buffer_head *bh, *head;
|
|
|
|
|
loff_t offset = page_offset(page);
|
|
|
|
|
|
2014-03-07 13:19:14 +08:00
|
|
|
|
if (!xfs_check_page_type(page, XFS_IO_DELALLOC, true))
|
2010-03-05 10:00:42 +08:00
|
|
|
|
goto out_invalidate;
|
|
|
|
|
|
2010-03-15 10:36:35 +08:00
|
|
|
|
if (XFS_FORCED_SHUTDOWN(ip->i_mount))
|
|
|
|
|
goto out_invalidate;
|
|
|
|
|
|
2011-03-07 07:00:35 +08:00
|
|
|
|
xfs_alert(ip->i_mount,
|
2010-03-05 10:00:42 +08:00
|
|
|
|
"page discard on page %p, inode 0x%llx, offset %llu.",
|
|
|
|
|
page, ip->i_ino, offset);
|
|
|
|
|
|
|
|
|
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
|
|
|
|
bh = head = page_buffers(page);
|
|
|
|
|
do {
|
|
|
|
|
int error;
|
2010-11-30 12:14:39 +08:00
|
|
|
|
xfs_fileoff_t start_fsb;
|
2010-03-05 10:00:42 +08:00
|
|
|
|
|
|
|
|
|
if (!buffer_delay(bh))
|
|
|
|
|
goto next_buffer;
|
|
|
|
|
|
2010-11-30 12:14:39 +08:00
|
|
|
|
start_fsb = XFS_B_TO_FSBT(ip->i_mount, offset);
|
|
|
|
|
error = xfs_bmap_punch_delalloc_range(ip, start_fsb, 1);
|
2010-03-05 10:00:42 +08:00
|
|
|
|
if (error) {
|
|
|
|
|
/* something screwed, just bail */
|
2010-03-15 10:36:35 +08:00
|
|
|
|
if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
|
2011-03-07 07:00:35 +08:00
|
|
|
|
xfs_alert(ip->i_mount,
|
2010-03-05 10:00:42 +08:00
|
|
|
|
"page discard unable to remove delalloc mapping.");
|
2010-03-15 10:36:35 +08:00
|
|
|
|
}
|
2010-03-05 10:00:42 +08:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
next_buffer:
|
2017-02-28 06:28:32 +08:00
|
|
|
|
offset += i_blocksize(inode);
|
2010-03-05 10:00:42 +08:00
|
|
|
|
|
|
|
|
|
} while ((bh = bh->b_this_page) != head);
|
|
|
|
|
|
|
|
|
|
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
|
|
|
|
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
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-04 00:11:34 +08:00
|
|
|
|
static int
|
|
|
|
|
xfs_map_cow(
|
|
|
|
|
struct xfs_writepage_ctx *wpc,
|
|
|
|
|
struct inode *inode,
|
|
|
|
|
loff_t offset,
|
|
|
|
|
unsigned int *new_type)
|
|
|
|
|
{
|
|
|
|
|
struct xfs_inode *ip = XFS_I(inode);
|
|
|
|
|
struct xfs_bmbt_irec imap;
|
2016-11-24 08:39:49 +08:00
|
|
|
|
bool is_cow = false;
|
2016-10-04 00:11:34 +08:00
|
|
|
|
int error;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If we already have a valid COW mapping keep using it.
|
|
|
|
|
*/
|
|
|
|
|
if (wpc->io_type == XFS_IO_COW) {
|
|
|
|
|
wpc->imap_valid = xfs_imap_valid(inode, &wpc->imap, offset);
|
|
|
|
|
if (wpc->imap_valid) {
|
|
|
|
|
*new_type = XFS_IO_COW;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Else we need to check if there is a COW mapping at this offset.
|
|
|
|
|
*/
|
|
|
|
|
xfs_ilock(ip, XFS_ILOCK_SHARED);
|
2016-11-24 08:39:49 +08:00
|
|
|
|
is_cow = xfs_reflink_find_cow_mapping(ip, offset, &imap);
|
2016-10-04 00:11:34 +08:00
|
|
|
|
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
|
|
|
|
|
|
|
|
|
if (!is_cow)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* And if the COW mapping has a delayed extent here we need to
|
|
|
|
|
* allocate real space for it now.
|
|
|
|
|
*/
|
2016-11-24 08:39:49 +08:00
|
|
|
|
if (isnullstartblock(imap.br_startblock)) {
|
2016-10-04 00:11:34 +08:00
|
|
|
|
error = xfs_iomap_write_allocate(ip, XFS_COW_FORK, offset,
|
|
|
|
|
&imap);
|
|
|
|
|
if (error)
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wpc->io_type = *new_type = XFS_IO_COW;
|
|
|
|
|
wpc->imap_valid = true;
|
|
|
|
|
wpc->imap = imap;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
|
* adding buffers to is cached on the writepage context, and if the new buffer
|
|
|
|
|
* 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,
|
|
|
|
|
loff_t offset,
|
|
|
|
|
__uint64_t end_offset)
|
|
|
|
|
{
|
2016-02-15 14:23:12 +08:00
|
|
|
|
LIST_HEAD(submit_list);
|
|
|
|
|
struct xfs_ioend *ioend, *next;
|
2016-02-15 14:21:37 +08:00
|
|
|
|
struct buffer_head *bh, *head;
|
2017-02-28 06:28:32 +08:00
|
|
|
|
ssize_t len = i_blocksize(inode);
|
2016-02-15 14:21:37 +08:00
|
|
|
|
int error = 0;
|
|
|
|
|
int count = 0;
|
2016-02-15 14:23:12 +08:00
|
|
|
|
int uptodate = 1;
|
2016-10-04 00:11:34 +08:00
|
|
|
|
unsigned int new_type;
|
2016-02-15 14:21:37 +08:00
|
|
|
|
|
|
|
|
|
bh = head = page_buffers(page);
|
|
|
|
|
offset = page_offset(page);
|
|
|
|
|
do {
|
|
|
|
|
if (offset >= end_offset)
|
|
|
|
|
break;
|
|
|
|
|
if (!buffer_uptodate(bh))
|
|
|
|
|
uptodate = 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* set_page_dirty dirties all buffers in a page, independent
|
|
|
|
|
* of their state. The dirty state however is entirely
|
|
|
|
|
* meaningless for holes (!mapped && uptodate), so skip
|
|
|
|
|
* buffers covering holes here.
|
|
|
|
|
*/
|
|
|
|
|
if (!buffer_mapped(bh) && buffer_uptodate(bh)) {
|
|
|
|
|
wpc->imap_valid = false;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-04 00:11:34 +08:00
|
|
|
|
if (buffer_unwritten(bh))
|
|
|
|
|
new_type = XFS_IO_UNWRITTEN;
|
|
|
|
|
else if (buffer_delay(bh))
|
|
|
|
|
new_type = XFS_IO_DELALLOC;
|
|
|
|
|
else if (buffer_uptodate(bh))
|
|
|
|
|
new_type = XFS_IO_OVERWRITE;
|
|
|
|
|
else {
|
2016-02-15 14:21:37 +08:00
|
|
|
|
if (PageUptodate(page))
|
|
|
|
|
ASSERT(buffer_mapped(bh));
|
|
|
|
|
/*
|
|
|
|
|
* This buffer is not uptodate and will not be
|
|
|
|
|
* written to disk. Ensure that we will put any
|
|
|
|
|
* subsequent writeable buffers into a new
|
|
|
|
|
* ioend.
|
|
|
|
|
*/
|
|
|
|
|
wpc->imap_valid = false;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-04 00:11:34 +08:00
|
|
|
|
if (xfs_is_reflink_inode(XFS_I(inode))) {
|
|
|
|
|
error = xfs_map_cow(wpc, inode, offset, &new_type);
|
|
|
|
|
if (error)
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (wpc->io_type != new_type) {
|
|
|
|
|
wpc->io_type = new_type;
|
|
|
|
|
wpc->imap_valid = false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-15 14:21:37 +08:00
|
|
|
|
if (wpc->imap_valid)
|
|
|
|
|
wpc->imap_valid = xfs_imap_valid(inode, &wpc->imap,
|
|
|
|
|
offset);
|
|
|
|
|
if (!wpc->imap_valid) {
|
|
|
|
|
error = xfs_map_blocks(inode, offset, &wpc->imap,
|
|
|
|
|
wpc->io_type);
|
|
|
|
|
if (error)
|
2016-02-15 14:23:12 +08:00
|
|
|
|
goto out;
|
2016-02-15 14:21:37 +08:00
|
|
|
|
wpc->imap_valid = xfs_imap_valid(inode, &wpc->imap,
|
|
|
|
|
offset);
|
|
|
|
|
}
|
|
|
|
|
if (wpc->imap_valid) {
|
|
|
|
|
lock_buffer(bh);
|
|
|
|
|
if (wpc->io_type != XFS_IO_OVERWRITE)
|
|
|
|
|
xfs_map_at_offset(inode, bh, &wpc->imap, offset);
|
2016-04-06 06:11:25 +08:00
|
|
|
|
xfs_add_to_ioend(inode, bh, offset, wpc, wbc, &submit_list);
|
2016-02-15 14:21:37 +08:00
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} while (offset += len, ((bh = bh->b_this_page) != head));
|
|
|
|
|
|
|
|
|
|
if (uptodate && bh == head)
|
|
|
|
|
SetPageUptodate(page);
|
|
|
|
|
|
2016-02-15 14:23:12 +08:00
|
|
|
|
ASSERT(wpc->ioend || list_empty(&submit_list));
|
2016-02-15 14:21:37 +08:00
|
|
|
|
|
2016-02-15 14:23:12 +08:00
|
|
|
|
out:
|
2016-02-15 14:21:37 +08:00
|
|
|
|
/*
|
2016-02-15 14:23:12 +08:00
|
|
|
|
* On error, we have to fail the ioend here because we have locked
|
|
|
|
|
* buffers in the ioend. If we don't do this, we'll deadlock
|
|
|
|
|
* invalidating the page as that tries to lock the buffers on the page.
|
|
|
|
|
* Also, 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
|
|
|
|
|
* buffers 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
|
|
|
|
|
* or it's buffers right 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
|
|
|
|
*/
|
2016-02-15 14:23:12 +08:00
|
|
|
|
if (count) {
|
|
|
|
|
xfs_start_page_writeback(page, !error);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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;
|
|
|
|
|
}
|
|
|
|
|
} else if (error) {
|
2016-02-15 14:21:37 +08:00
|
|
|
|
xfs_aops_discard_page(page);
|
|
|
|
|
ClearPageUptodate(page);
|
|
|
|
|
unlock_page(page);
|
2016-02-15 14:23:12 +08:00
|
|
|
|
} else {
|
|
|
|
|
/*
|
|
|
|
|
* We can end up here with no error and nothing to write if we
|
|
|
|
|
* race with a partial page truncate on a sub-page block sized
|
|
|
|
|
* filesystem. In that case we need to mark the page clean.
|
|
|
|
|
*/
|
|
|
|
|
xfs_start_page_writeback(page, 1);
|
|
|
|
|
end_page_writeback(page);
|
2016-02-15 14:21:37 +08:00
|
|
|
|
}
|
2016-02-15 14:23:12 +08:00
|
|
|
|
|
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.
|
|
|
|
|
* For any other dirty buffer heads on the page we should flush them.
|
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;
|
|
|
|
|
__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
|
|
|
|
|
2010-06-24 07:46:01 +08:00
|
|
|
|
ASSERT(page_has_buffers(page));
|
|
|
|
|
|
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
|
|
|
|
*/
|
2014-06-06 14:05:15 +08:00
|
|
|
|
if (WARN_ON_ONCE(current->flags & PF_FSTRANS))
|
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
|
|
|
|
}
|
|
|
|
|
|
2016-02-15 14:23:12 +08:00
|
|
|
|
return xfs_writepage_map(wpc, wbc, inode, page, offset, 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-27 07:19:55 +08:00
|
|
|
|
if (dax_mapping(mapping))
|
|
|
|
|
return dax_writeback_mapping_range(mapping,
|
|
|
|
|
xfs_find_bdev_for_inode(mapping->host), wbc);
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
2006-03-14 10:26:27 +08:00
|
|
|
|
/*
|
|
|
|
|
* Called to move a page into cleanable state - and from there
|
2010-06-24 07:45:48 +08:00
|
|
|
|
* to be released. The page should already be clean. We always
|
2006-03-14 10:26:27 +08:00
|
|
|
|
* have buffer heads in this call.
|
|
|
|
|
*
|
2010-06-24 07:45:48 +08:00
|
|
|
|
* Returns 1 if the page is ok to release, 0 otherwise.
|
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)
|
|
|
|
|
{
|
2010-06-24 07:46:01 +08:00
|
|
|
|
int delalloc, unwritten;
|
2006-03-14 10:26:27 +08:00
|
|
|
|
|
2013-05-22 11:58:01 +08:00
|
|
|
|
trace_xfs_releasepage(page->mapping->host, page, 0, 0);
|
2006-03-17 14:26:25 +08:00
|
|
|
|
|
2016-07-22 07:50:38 +08:00
|
|
|
|
/*
|
|
|
|
|
* mm accommodates an old ext3 case where clean pages might not have had
|
|
|
|
|
* the dirty bit cleared. Thus, it can send actual dirty pages to
|
|
|
|
|
* ->releasepage() via shrink_active_list(). Conversely,
|
|
|
|
|
* block_invalidatepage() can send pages that are still marked dirty
|
|
|
|
|
* but otherwise have invalidated buffers.
|
|
|
|
|
*
|
2017-01-12 02:20:04 +08:00
|
|
|
|
* We want to release the latter to avoid unnecessary buildup of the
|
|
|
|
|
* LRU, skip the former and warn if we've left any lingering
|
|
|
|
|
* delalloc/unwritten buffers on clean pages. Skip pages with delalloc
|
|
|
|
|
* or unwritten buffers and warn if the page is not dirty. Otherwise
|
|
|
|
|
* try to release the buffers.
|
2016-07-22 07:50:38 +08:00
|
|
|
|
*/
|
2010-06-24 07:46:01 +08:00
|
|
|
|
xfs_count_page_state(page, &delalloc, &unwritten);
|
2006-03-14 10:26:27 +08:00
|
|
|
|
|
2017-01-12 02:20:04 +08:00
|
|
|
|
if (delalloc) {
|
|
|
|
|
WARN_ON_ONCE(!PageDirty(page));
|
2006-03-14 10:26:27 +08:00
|
|
|
|
return 0;
|
2017-01-12 02:20:04 +08:00
|
|
|
|
}
|
|
|
|
|
if (unwritten) {
|
|
|
|
|
WARN_ON_ONCE(!PageDirty(page));
|
2006-03-14 10:26:27 +08:00
|
|
|
|
return 0;
|
2017-01-12 02:20:04 +08:00
|
|
|
|
}
|
2006-03-14 10:26:27 +08:00
|
|
|
|
|
|
|
|
|
return try_to_free_buffers(page);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 19:58:21 +08:00
|
|
|
|
/*
|
|
|
|
|
* If this is O_DIRECT or the mpage code calling tell them how large the mapping
|
|
|
|
|
* is, so that we can avoid repeated get_blocks calls.
|
|
|
|
|
*
|
|
|
|
|
* If the mapping spans EOF, then we have to break the mapping up as the mapping
|
|
|
|
|
* for blocks beyond EOF must be marked new so that sub block regions can be
|
|
|
|
|
* correctly zeroed. We can't do this for mappings within EOF unless the mapping
|
|
|
|
|
* was just allocated or is unwritten, otherwise the callers would overwrite
|
|
|
|
|
* existing data with zeros. Hence we have to split the mapping into a range up
|
|
|
|
|
* to and including EOF, and a second mapping for beyond EOF.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
xfs_map_trim_size(
|
|
|
|
|
struct inode *inode,
|
|
|
|
|
sector_t iblock,
|
|
|
|
|
struct buffer_head *bh_result,
|
|
|
|
|
struct xfs_bmbt_irec *imap,
|
|
|
|
|
xfs_off_t offset,
|
|
|
|
|
ssize_t size)
|
|
|
|
|
{
|
|
|
|
|
xfs_off_t mapping_size;
|
|
|
|
|
|
|
|
|
|
mapping_size = imap->br_startoff + imap->br_blockcount - iblock;
|
|
|
|
|
mapping_size <<= inode->i_blkbits;
|
|
|
|
|
|
|
|
|
|
ASSERT(mapping_size > 0);
|
|
|
|
|
if (mapping_size > size)
|
|
|
|
|
mapping_size = size;
|
|
|
|
|
if (offset < i_size_read(inode) &&
|
|
|
|
|
offset + mapping_size >= i_size_read(inode)) {
|
|
|
|
|
/* limit mapping to block that spans EOF */
|
|
|
|
|
mapping_size = roundup_64(i_size_read(inode) - offset,
|
2017-02-28 06:28:32 +08:00
|
|
|
|
i_blocksize(inode));
|
2015-04-16 19:58:21 +08:00
|
|
|
|
}
|
|
|
|
|
if (mapping_size > LONG_MAX)
|
|
|
|
|
mapping_size = LONG_MAX;
|
|
|
|
|
|
|
|
|
|
bh_result->b_size = mapping_size;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-04 00:11:37 +08:00
|
|
|
|
static int
|
2016-11-30 11:37:15 +08:00
|
|
|
|
xfs_get_blocks(
|
2005-04-17 06:20:36 +08:00
|
|
|
|
struct inode *inode,
|
|
|
|
|
sector_t iblock,
|
|
|
|
|
struct buffer_head *bh_result,
|
2016-11-30 11:37:15 +08:00
|
|
|
|
int create)
|
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;
|
|
|
|
|
xfs_fileoff_t offset_fsb, end_fsb;
|
|
|
|
|
int error = 0;
|
|
|
|
|
int lockmode = 0;
|
2010-04-28 20:28:56 +08:00
|
|
|
|
struct xfs_bmbt_irec imap;
|
2010-12-10 16:42:20 +08:00
|
|
|
|
int nimaps = 1;
|
2005-11-02 12:13:13 +08:00
|
|
|
|
xfs_off_t offset;
|
|
|
|
|
ssize_t size;
|
2010-12-10 16:42:20 +08:00
|
|
|
|
|
2016-11-30 11:37:15 +08:00
|
|
|
|
BUG_ON(create);
|
2016-06-21 07:53:45 +08:00
|
|
|
|
|
2010-12-10 16:42:20 +08:00
|
|
|
|
if (XFS_FORCED_SHUTDOWN(mp))
|
2014-06-22 13:04:54 +08:00
|
|
|
|
return -EIO;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
2005-11-02 12:13:13 +08:00
|
|
|
|
offset = (xfs_off_t)iblock << inode->i_blkbits;
|
2017-02-28 06:28:32 +08:00
|
|
|
|
ASSERT(bh_result->b_size >= i_blocksize(inode));
|
2006-03-29 08:44:40 +08:00
|
|
|
|
size = bh_result->b_size;
|
2008-09-17 14:50:14 +08:00
|
|
|
|
|
2016-11-30 11:37:15 +08:00
|
|
|
|
if (offset >= i_size_read(inode))
|
2008-09-17 14:50:14 +08:00
|
|
|
|
return 0;
|
|
|
|
|
|
2012-03-27 22:34:50 +08:00
|
|
|
|
/*
|
|
|
|
|
* Direct I/O is usually done on preallocated files, so try getting
|
2016-06-21 07:53:45 +08:00
|
|
|
|
* a block mapping without an exclusive lock first.
|
2012-03-27 22:34:50 +08:00
|
|
|
|
*/
|
2016-06-21 07:53:45 +08:00
|
|
|
|
lockmode = xfs_ilock_data_map_shared(ip);
|
2010-06-24 09:44:35 +08:00
|
|
|
|
|
2012-06-08 13:44:53 +08:00
|
|
|
|
ASSERT(offset <= mp->m_super->s_maxbytes);
|
|
|
|
|
if (offset + size > mp->m_super->s_maxbytes)
|
|
|
|
|
size = mp->m_super->s_maxbytes - offset;
|
2010-12-10 16:42:20 +08:00
|
|
|
|
end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size);
|
|
|
|
|
offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
|
|
|
|
|
2016-11-30 11:37:15 +08:00
|
|
|
|
error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
|
|
|
|
|
&imap, &nimaps, XFS_BMAPI_ENTIRE);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
if (error)
|
2010-12-10 16:42:20 +08:00
|
|
|
|
goto out_unlock;
|
|
|
|
|
|
2016-11-30 11:37:15 +08:00
|
|
|
|
if (nimaps) {
|
2015-04-16 19:59:07 +08:00
|
|
|
|
trace_xfs_get_blocks_found(ip, offset, size,
|
2017-03-29 05:53:36 +08:00
|
|
|
|
imap.br_state == XFS_EXT_UNWRITTEN ?
|
|
|
|
|
XFS_IO_UNWRITTEN : XFS_IO_OVERWRITE, &imap);
|
2012-03-27 22:34:50 +08:00
|
|
|
|
xfs_iunlock(ip, lockmode);
|
2010-12-10 16:42:20 +08:00
|
|
|
|
} else {
|
|
|
|
|
trace_xfs_get_blocks_notfound(ip, offset, size);
|
|
|
|
|
goto out_unlock;
|
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
2015-04-16 19:58:21 +08:00
|
|
|
|
/* trim mapping down to size requested */
|
2016-06-21 07:53:45 +08:00
|
|
|
|
xfs_map_trim_size(inode, iblock, bh_result, &imap, offset, size);
|
2015-04-16 19:58:21 +08:00
|
|
|
|
|
2015-04-16 19:57:48 +08:00
|
|
|
|
/*
|
|
|
|
|
* For unwritten extents do not report a disk address in the buffered
|
|
|
|
|
* read case (treat as if we're reading into a hole).
|
|
|
|
|
*/
|
2017-03-29 05:53:35 +08:00
|
|
|
|
if (xfs_bmap_is_real_extent(&imap))
|
2015-04-16 19:57:48 +08:00
|
|
|
|
xfs_map_buffer(inode, bh_result, &imap, offset);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
2006-03-29 08:44:40 +08:00
|
|
|
|
/*
|
|
|
|
|
* If this is a realtime file, data may be on a different device.
|
|
|
|
|
* to that pointed to from the buffer_head b_bdev currently.
|
|
|
|
|
*/
|
2010-04-28 20:28:52 +08:00
|
|
|
|
bh_result->b_bdev = xfs_find_bdev_for_inode(inode);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
return 0;
|
2010-12-10 16:42:20 +08:00
|
|
|
|
|
|
|
|
|
out_unlock:
|
|
|
|
|
xfs_iunlock(ip, lockmode);
|
2014-06-25 12:58:08 +08:00
|
|
|
|
return error;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-08 11:40:51 +08:00
|
|
|
|
STATIC ssize_t
|
|
|
|
|
xfs_vm_direct_IO(
|
2015-06-04 07:19:15 +08:00
|
|
|
|
struct kiocb *iocb,
|
2016-04-07 23:51:58 +08:00
|
|
|
|
struct iov_iter *iter)
|
2015-06-04 07:19:15 +08:00
|
|
|
|
{
|
2013-07-16 13:11:16 +08:00
|
|
|
|
/*
|
2016-07-20 09:38:01 +08:00
|
|
|
|
* We just need the method present so that open/fcntl allow direct I/O.
|
2013-07-16 13:11:16 +08:00
|
|
|
|
*/
|
2016-07-20 09:38:01 +08:00
|
|
|
|
return -EINVAL;
|
2006-03-14 10:26:27 +08:00
|
|
|
|
}
|
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)
|
|
|
|
|
{
|
|
|
|
|
struct inode *inode = (struct inode *)mapping->host;
|
2007-08-29 08:58:01 +08:00
|
|
|
|
struct xfs_inode *ip = XFS_I(inode);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
2010-06-24 09:57:09 +08:00
|
|
|
|
trace_xfs_vm_bmap(XFS_I(inode));
|
2016-10-04 00:11:36 +08:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The swap code (ab-)uses ->bmap to get a block mapping and then
|
|
|
|
|
* bypasseѕ the file system for actual I/O. We really can't allow
|
|
|
|
|
* that on reflinks inodes, so we have to skip out here. And yes,
|
|
|
|
|
* 0 is the magic code for a bmap error..
|
|
|
|
|
*/
|
2016-11-30 11:33:25 +08:00
|
|
|
|
if (xfs_is_reflink_inode(ip))
|
2016-10-04 00:11:36 +08:00
|
|
|
|
return 0;
|
2016-11-30 11:33:25 +08:00
|
|
|
|
|
2012-11-12 19:53:56 +08:00
|
|
|
|
filemap_write_and_wait(mapping);
|
2006-03-29 08:44:40 +08:00
|
|
|
|
return generic_block_bmap(mapping, block, xfs_get_blocks);
|
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);
|
2006-03-29 08:44:40 +08:00
|
|
|
|
return mpage_readpage(page, xfs_get_blocks);
|
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);
|
2006-03-29 08:44:40 +08:00
|
|
|
|
return mpage_readpages(mapping, pages, nr_pages, xfs_get_blocks);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
/*
|
|
|
|
|
* This is basically a copy of __set_page_dirty_buffers() with one
|
|
|
|
|
* small tweak: buffers beyond EOF do not get marked dirty. If we mark them
|
|
|
|
|
* dirty, we'll never be able to clean them because we don't write buffers
|
|
|
|
|
* beyond EOF, and that means we can't invalidate pages that span EOF
|
|
|
|
|
* that have been marked dirty. Further, the dirty state can leak into
|
|
|
|
|
* the file interior if the file is extended, resulting in all sorts of
|
|
|
|
|
* bad things happening as the state does not match the underlying data.
|
|
|
|
|
*
|
|
|
|
|
* XXX: this really indicates that bufferheads in XFS need to die. Warts like
|
|
|
|
|
* this only exist because of bufferheads and how the generic code manages them.
|
|
|
|
|
*/
|
|
|
|
|
STATIC int
|
|
|
|
|
xfs_vm_set_page_dirty(
|
|
|
|
|
struct page *page)
|
|
|
|
|
{
|
|
|
|
|
struct address_space *mapping = page->mapping;
|
|
|
|
|
struct inode *inode = mapping->host;
|
|
|
|
|
loff_t end_offset;
|
|
|
|
|
loff_t offset;
|
|
|
|
|
int newly_dirty;
|
|
|
|
|
|
|
|
|
|
if (unlikely(!mapping))
|
|
|
|
|
return !TestSetPageDirty(page);
|
|
|
|
|
|
|
|
|
|
end_offset = i_size_read(inode);
|
|
|
|
|
offset = page_offset(page);
|
|
|
|
|
|
|
|
|
|
spin_lock(&mapping->private_lock);
|
|
|
|
|
if (page_has_buffers(page)) {
|
|
|
|
|
struct buffer_head *head = page_buffers(page);
|
|
|
|
|
struct buffer_head *bh = head;
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
if (offset < end_offset)
|
|
|
|
|
set_buffer_dirty(bh);
|
|
|
|
|
bh = bh->b_this_page;
|
2017-02-28 06:28:32 +08:00
|
|
|
|
offset += i_blocksize(inode);
|
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
|
|
|
|
} while (bh != head);
|
|
|
|
|
}
|
memcg: add per cgroup dirty page accounting
When modifying PG_Dirty on cached file pages, update the new
MEM_CGROUP_STAT_DIRTY counter. This is done in the same places where
global NR_FILE_DIRTY is managed. The new memcg stat is visible in the
per memcg memory.stat cgroupfs file. The most recent past attempt at
this was http://thread.gmane.org/gmane.linux.kernel.cgroups/8632
The new accounting supports future efforts to add per cgroup dirty
page throttling and writeback. It also helps an administrator break
down a container's memory usage and provides evidence to understand
memcg oom kills (the new dirty count is included in memcg oom kill
messages).
The ability to move page accounting between memcg
(memory.move_charge_at_immigrate) makes this accounting more
complicated than the global counter. The existing
mem_cgroup_{begin,end}_page_stat() lock is used to serialize move
accounting with stat updates.
Typical update operation:
memcg = mem_cgroup_begin_page_stat(page)
if (TestSetPageDirty()) {
[...]
mem_cgroup_update_page_stat(memcg)
}
mem_cgroup_end_page_stat(memcg)
Summary of mem_cgroup_end_page_stat() overhead:
- Without CONFIG_MEMCG it's a no-op
- With CONFIG_MEMCG and no inter memcg task movement, it's just
rcu_read_lock()
- With CONFIG_MEMCG and inter memcg task movement, it's
rcu_read_lock() + spin_lock_irqsave()
A memcg parameter is added to several routines because their callers
now grab mem_cgroup_begin_page_stat() which returns the memcg later
needed by for mem_cgroup_update_page_stat().
Because mem_cgroup_begin_page_stat() may disable interrupts, some
adjustments are needed:
- move __mark_inode_dirty() from __set_page_dirty() to its caller.
__mark_inode_dirty() locking does not want interrupts disabled.
- use spin_lock_irqsave(tree_lock) rather than spin_lock_irq() in
__delete_from_page_cache(), replace_page_cache_page(),
invalidate_complete_page2(), and __remove_mapping().
text data bss dec hex filename
8925147 1774832 1785856 12485835 be84cb vmlinux-!CONFIG_MEMCG-before
8925339 1774832 1785856 12486027 be858b vmlinux-!CONFIG_MEMCG-after
+192 text bytes
8965977 1784992 1785856 12536825 bf4bf9 vmlinux-CONFIG_MEMCG-before
8966750 1784992 1785856 12537598 bf4efe vmlinux-CONFIG_MEMCG-after
+773 text bytes
Performance tests run on v4.0-rc1-36-g4f671fe2f952. Lower is better for
all metrics, they're all wall clock or cycle counts. The read and write
fault benchmarks just measure fault time, they do not include I/O time.
* CONFIG_MEMCG not set:
baseline patched
kbuild 1m25.030000(+-0.088% 3 samples) 1m25.426667(+-0.120% 3 samples)
dd write 100 MiB 0.859211561 +-15.10% 0.874162885 +-15.03%
dd write 200 MiB 1.670653105 +-17.87% 1.669384764 +-11.99%
dd write 1000 MiB 8.434691190 +-14.15% 8.474733215 +-14.77%
read fault cycles 254.0(+-0.000% 10 samples) 253.0(+-0.000% 10 samples)
write fault cycles 2021.2(+-3.070% 10 samples) 1984.5(+-1.036% 10 samples)
* CONFIG_MEMCG=y root_memcg:
baseline patched
kbuild 1m25.716667(+-0.105% 3 samples) 1m25.686667(+-0.153% 3 samples)
dd write 100 MiB 0.855650830 +-14.90% 0.887557919 +-14.90%
dd write 200 MiB 1.688322953 +-12.72% 1.667682724 +-13.33%
dd write 1000 MiB 8.418601605 +-14.30% 8.673532299 +-15.00%
read fault cycles 266.0(+-0.000% 10 samples) 266.0(+-0.000% 10 samples)
write fault cycles 2051.7(+-1.349% 10 samples) 2049.6(+-1.686% 10 samples)
* CONFIG_MEMCG=y non-root_memcg:
baseline patched
kbuild 1m26.120000(+-0.273% 3 samples) 1m25.763333(+-0.127% 3 samples)
dd write 100 MiB 0.861723964 +-15.25% 0.818129350 +-14.82%
dd write 200 MiB 1.669887569 +-13.30% 1.698645885 +-13.27%
dd write 1000 MiB 8.383191730 +-14.65% 8.351742280 +-14.52%
read fault cycles 265.7(+-0.172% 10 samples) 267.0(+-0.000% 10 samples)
write fault cycles 2070.6(+-1.512% 10 samples) 2084.4(+-2.148% 10 samples)
As expected anon page faults are not affected by this patch.
tj: Updated to apply on top of the recent cancel_dirty_page() changes.
Signed-off-by: Sha Zhengju <handai.szj@gmail.com>
Signed-off-by: Greg Thelen <gthelen@google.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:16 +08:00
|
|
|
|
/*
|
2016-03-16 05:57:04 +08:00
|
|
|
|
* Lock out page->mem_cgroup migration to keep PageDirty
|
|
|
|
|
* synchronized with per-memcg dirty page counters.
|
memcg: add per cgroup dirty page accounting
When modifying PG_Dirty on cached file pages, update the new
MEM_CGROUP_STAT_DIRTY counter. This is done in the same places where
global NR_FILE_DIRTY is managed. The new memcg stat is visible in the
per memcg memory.stat cgroupfs file. The most recent past attempt at
this was http://thread.gmane.org/gmane.linux.kernel.cgroups/8632
The new accounting supports future efforts to add per cgroup dirty
page throttling and writeback. It also helps an administrator break
down a container's memory usage and provides evidence to understand
memcg oom kills (the new dirty count is included in memcg oom kill
messages).
The ability to move page accounting between memcg
(memory.move_charge_at_immigrate) makes this accounting more
complicated than the global counter. The existing
mem_cgroup_{begin,end}_page_stat() lock is used to serialize move
accounting with stat updates.
Typical update operation:
memcg = mem_cgroup_begin_page_stat(page)
if (TestSetPageDirty()) {
[...]
mem_cgroup_update_page_stat(memcg)
}
mem_cgroup_end_page_stat(memcg)
Summary of mem_cgroup_end_page_stat() overhead:
- Without CONFIG_MEMCG it's a no-op
- With CONFIG_MEMCG and no inter memcg task movement, it's just
rcu_read_lock()
- With CONFIG_MEMCG and inter memcg task movement, it's
rcu_read_lock() + spin_lock_irqsave()
A memcg parameter is added to several routines because their callers
now grab mem_cgroup_begin_page_stat() which returns the memcg later
needed by for mem_cgroup_update_page_stat().
Because mem_cgroup_begin_page_stat() may disable interrupts, some
adjustments are needed:
- move __mark_inode_dirty() from __set_page_dirty() to its caller.
__mark_inode_dirty() locking does not want interrupts disabled.
- use spin_lock_irqsave(tree_lock) rather than spin_lock_irq() in
__delete_from_page_cache(), replace_page_cache_page(),
invalidate_complete_page2(), and __remove_mapping().
text data bss dec hex filename
8925147 1774832 1785856 12485835 be84cb vmlinux-!CONFIG_MEMCG-before
8925339 1774832 1785856 12486027 be858b vmlinux-!CONFIG_MEMCG-after
+192 text bytes
8965977 1784992 1785856 12536825 bf4bf9 vmlinux-CONFIG_MEMCG-before
8966750 1784992 1785856 12537598 bf4efe vmlinux-CONFIG_MEMCG-after
+773 text bytes
Performance tests run on v4.0-rc1-36-g4f671fe2f952. Lower is better for
all metrics, they're all wall clock or cycle counts. The read and write
fault benchmarks just measure fault time, they do not include I/O time.
* CONFIG_MEMCG not set:
baseline patched
kbuild 1m25.030000(+-0.088% 3 samples) 1m25.426667(+-0.120% 3 samples)
dd write 100 MiB 0.859211561 +-15.10% 0.874162885 +-15.03%
dd write 200 MiB 1.670653105 +-17.87% 1.669384764 +-11.99%
dd write 1000 MiB 8.434691190 +-14.15% 8.474733215 +-14.77%
read fault cycles 254.0(+-0.000% 10 samples) 253.0(+-0.000% 10 samples)
write fault cycles 2021.2(+-3.070% 10 samples) 1984.5(+-1.036% 10 samples)
* CONFIG_MEMCG=y root_memcg:
baseline patched
kbuild 1m25.716667(+-0.105% 3 samples) 1m25.686667(+-0.153% 3 samples)
dd write 100 MiB 0.855650830 +-14.90% 0.887557919 +-14.90%
dd write 200 MiB 1.688322953 +-12.72% 1.667682724 +-13.33%
dd write 1000 MiB 8.418601605 +-14.30% 8.673532299 +-15.00%
read fault cycles 266.0(+-0.000% 10 samples) 266.0(+-0.000% 10 samples)
write fault cycles 2051.7(+-1.349% 10 samples) 2049.6(+-1.686% 10 samples)
* CONFIG_MEMCG=y non-root_memcg:
baseline patched
kbuild 1m26.120000(+-0.273% 3 samples) 1m25.763333(+-0.127% 3 samples)
dd write 100 MiB 0.861723964 +-15.25% 0.818129350 +-14.82%
dd write 200 MiB 1.669887569 +-13.30% 1.698645885 +-13.27%
dd write 1000 MiB 8.383191730 +-14.65% 8.351742280 +-14.52%
read fault cycles 265.7(+-0.172% 10 samples) 267.0(+-0.000% 10 samples)
write fault cycles 2070.6(+-1.512% 10 samples) 2084.4(+-2.148% 10 samples)
As expected anon page faults are not affected by this patch.
tj: Updated to apply on top of the recent cancel_dirty_page() changes.
Signed-off-by: Sha Zhengju <handai.szj@gmail.com>
Signed-off-by: Greg Thelen <gthelen@google.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:16 +08:00
|
|
|
|
*/
|
2016-03-16 05:57:22 +08:00
|
|
|
|
lock_page_memcg(page);
|
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
|
|
|
|
newly_dirty = !TestSetPageDirty(page);
|
|
|
|
|
spin_unlock(&mapping->private_lock);
|
|
|
|
|
|
|
|
|
|
if (newly_dirty) {
|
|
|
|
|
/* sigh - __set_page_dirty() is static, so copy it here, too */
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
|
|
spin_lock_irqsave(&mapping->tree_lock, flags);
|
|
|
|
|
if (page->mapping) { /* Race with truncate? */
|
|
|
|
|
WARN_ON_ONCE(!PageUptodate(page));
|
2016-03-16 05:57:22 +08:00
|
|
|
|
account_page_dirtied(page, mapping);
|
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
|
|
|
|
radix_tree_tag_set(&mapping->page_tree,
|
|
|
|
|
page_index(page), PAGECACHE_TAG_DIRTY);
|
|
|
|
|
}
|
|
|
|
|
spin_unlock_irqrestore(&mapping->tree_lock, flags);
|
|
|
|
|
}
|
2016-03-16 05:57:22 +08:00
|
|
|
|
unlock_page_memcg(page);
|
memcg: add per cgroup dirty page accounting
When modifying PG_Dirty on cached file pages, update the new
MEM_CGROUP_STAT_DIRTY counter. This is done in the same places where
global NR_FILE_DIRTY is managed. The new memcg stat is visible in the
per memcg memory.stat cgroupfs file. The most recent past attempt at
this was http://thread.gmane.org/gmane.linux.kernel.cgroups/8632
The new accounting supports future efforts to add per cgroup dirty
page throttling and writeback. It also helps an administrator break
down a container's memory usage and provides evidence to understand
memcg oom kills (the new dirty count is included in memcg oom kill
messages).
The ability to move page accounting between memcg
(memory.move_charge_at_immigrate) makes this accounting more
complicated than the global counter. The existing
mem_cgroup_{begin,end}_page_stat() lock is used to serialize move
accounting with stat updates.
Typical update operation:
memcg = mem_cgroup_begin_page_stat(page)
if (TestSetPageDirty()) {
[...]
mem_cgroup_update_page_stat(memcg)
}
mem_cgroup_end_page_stat(memcg)
Summary of mem_cgroup_end_page_stat() overhead:
- Without CONFIG_MEMCG it's a no-op
- With CONFIG_MEMCG and no inter memcg task movement, it's just
rcu_read_lock()
- With CONFIG_MEMCG and inter memcg task movement, it's
rcu_read_lock() + spin_lock_irqsave()
A memcg parameter is added to several routines because their callers
now grab mem_cgroup_begin_page_stat() which returns the memcg later
needed by for mem_cgroup_update_page_stat().
Because mem_cgroup_begin_page_stat() may disable interrupts, some
adjustments are needed:
- move __mark_inode_dirty() from __set_page_dirty() to its caller.
__mark_inode_dirty() locking does not want interrupts disabled.
- use spin_lock_irqsave(tree_lock) rather than spin_lock_irq() in
__delete_from_page_cache(), replace_page_cache_page(),
invalidate_complete_page2(), and __remove_mapping().
text data bss dec hex filename
8925147 1774832 1785856 12485835 be84cb vmlinux-!CONFIG_MEMCG-before
8925339 1774832 1785856 12486027 be858b vmlinux-!CONFIG_MEMCG-after
+192 text bytes
8965977 1784992 1785856 12536825 bf4bf9 vmlinux-CONFIG_MEMCG-before
8966750 1784992 1785856 12537598 bf4efe vmlinux-CONFIG_MEMCG-after
+773 text bytes
Performance tests run on v4.0-rc1-36-g4f671fe2f952. Lower is better for
all metrics, they're all wall clock or cycle counts. The read and write
fault benchmarks just measure fault time, they do not include I/O time.
* CONFIG_MEMCG not set:
baseline patched
kbuild 1m25.030000(+-0.088% 3 samples) 1m25.426667(+-0.120% 3 samples)
dd write 100 MiB 0.859211561 +-15.10% 0.874162885 +-15.03%
dd write 200 MiB 1.670653105 +-17.87% 1.669384764 +-11.99%
dd write 1000 MiB 8.434691190 +-14.15% 8.474733215 +-14.77%
read fault cycles 254.0(+-0.000% 10 samples) 253.0(+-0.000% 10 samples)
write fault cycles 2021.2(+-3.070% 10 samples) 1984.5(+-1.036% 10 samples)
* CONFIG_MEMCG=y root_memcg:
baseline patched
kbuild 1m25.716667(+-0.105% 3 samples) 1m25.686667(+-0.153% 3 samples)
dd write 100 MiB 0.855650830 +-14.90% 0.887557919 +-14.90%
dd write 200 MiB 1.688322953 +-12.72% 1.667682724 +-13.33%
dd write 1000 MiB 8.418601605 +-14.30% 8.673532299 +-15.00%
read fault cycles 266.0(+-0.000% 10 samples) 266.0(+-0.000% 10 samples)
write fault cycles 2051.7(+-1.349% 10 samples) 2049.6(+-1.686% 10 samples)
* CONFIG_MEMCG=y non-root_memcg:
baseline patched
kbuild 1m26.120000(+-0.273% 3 samples) 1m25.763333(+-0.127% 3 samples)
dd write 100 MiB 0.861723964 +-15.25% 0.818129350 +-14.82%
dd write 200 MiB 1.669887569 +-13.30% 1.698645885 +-13.27%
dd write 1000 MiB 8.383191730 +-14.65% 8.351742280 +-14.52%
read fault cycles 265.7(+-0.172% 10 samples) 267.0(+-0.000% 10 samples)
write fault cycles 2070.6(+-1.512% 10 samples) 2084.4(+-2.148% 10 samples)
As expected anon page faults are not affected by this patch.
tj: Updated to apply on top of the recent cancel_dirty_page() changes.
Signed-off-by: Sha Zhengju <handai.szj@gmail.com>
Signed-off-by: Greg Thelen <gthelen@google.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jens Axboe <axboe@fb.com>
2015-05-23 05:13:16 +08:00
|
|
|
|
if (newly_dirty)
|
|
|
|
|
__mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
|
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
|
|
|
|
return newly_dirty;
|
|
|
|
|
}
|
|
|
|
|
|
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,
|
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
|
|
|
|
.set_page_dirty = xfs_vm_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,
|
|
|
|
|
.direct_IO = xfs_vm_direct_IO,
|
2006-02-01 19:05:41 +08:00
|
|
|
|
.migratepage = buffer_migrate_page,
|
2009-03-29 15:53:38 +08:00
|
|
|
|
.is_partially_uptodate = block_is_partially_uptodate,
|
2009-09-16 17:50:16 +08:00
|
|
|
|
.error_remove_page = generic_error_remove_page,
|
2005-04-17 06:20:36 +08:00
|
|
|
|
};
|