Commit 577c516f authored by Andrew Morton's avatar Andrew Morton Committed by Jaroslav Kysela

[PATCH] remove PF_SYNC

current->flags:PF_SYNC was a hack I added because I didn't want to
change all ->writepage implementations.

It's foul.  And it means that if someone happens to run direct page
reclaim within the context of (say) sys_sync, the writepage invokations
from the VM will be treated as "data integrity" operations, not "memory
cleansing" operations, which would cause latency.

So the patch removes PF_SYNC and adds an extra arg to a_ops->writepage.
 It is the `writeback_control' structure which contains the full context
information about why writepage was called.

The initial version of this patch just passed in a bare `int sync', but
the XFS team need more info so they can perform writearound from within
page reclaim.

The patch also adds writeback_control.for_reclaim, so writepage
implementations can inspect that to work out the call context rather
than peeking at current->flags:PF_MEMALLOC.
parent 8725c3fc
......@@ -133,10 +133,10 @@ unlocks and drops the reference.
--------------------------- address_space_operations --------------------------
prototypes:
int (*writepage)(struct page *);
int (*writepage)(struct page *page, struct writeback_control *wbc);
int (*readpage)(struct file *, struct page *);
int (*sync_page)(struct page *);
int (*writepages)(struct address_space *, int *nr_to_write);
int (*writepages)(struct address_space *, struct writeback_control *);
int (*set_page_dirty)(struct page *page);
int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
......@@ -172,15 +172,16 @@ I/O against them. They come unlocked upon I/O completion.
->writepage() is used for two purposes: for "memory cleansing" and for
"sync". These are quite different operations and the behaviour may differ
depending upon the mode. (Yes, there should be two a_ops for this, or
writepage should take a writeback_control*)
depending upon the mode.
If writepage is called for sync (current->flags & PF_SYNC) then it *must*
write the page, even if that would involve blocking on in-progress I/O.
If writepage is called for sync (wbc->sync_mode != WBC_SYNC_NONE) then
it *must* start I/O against the page, even if that would involve
blocking on in-progress I/O.
If writepage is called for memory cleansing (!(current->flags & PF_SYNC))
then its role is to get as much writeout underway as possible. So writepage
should try to avoid blocking against currently-in-progress I/O.
If writepage is called for memory cleansing (sync_mode ==
WBC_SYNC_NONE) then its role is to get as much writeout underway as
possible. So writepage should try to avoid blocking against
currently-in-progress I/O.
If the filesystem is not called for "sync" and it determines that it
would need to block against in-progress I/O to be able to start new I/O
......
......@@ -264,7 +264,7 @@ struct inode_operations {
int (*readlink) (struct dentry *, char *,int);
struct dentry * (*follow_link) (struct dentry *, struct dentry *);
int (*readpage) (struct file *, struct page *);
int (*writepage) (struct file *, struct page *);
int (*writepage) (struct page *page, struct writeback_control *wbc);
int (*bmap) (struct inode *,int);
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int);
......
......@@ -151,9 +151,10 @@ MODULE_PARM(wqs, "i");
/* Page cache stuff */
/* writepage() - should never be called - catch it anyway */
static int blkmtd_writepage(struct page *page)
static int blkmtd_writepage(struct page *page, struct writeback_control *wbc)
{
printk("blkmtd: writepage called!!!\n");
unlock_page(page);
return -EIO;
}
......
......@@ -51,9 +51,9 @@ adfs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh, int
return 0;
}
static int adfs_writepage(struct page *page)
static int adfs_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page, adfs_get_block);
return block_write_full_page(page, adfs_get_block, wbc);
}
static int adfs_readpage(struct file *file, struct page *page)
......
......@@ -407,9 +407,9 @@ affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_resul
return -ENOSPC;
}
static int affs_writepage(struct page *page)
static int affs_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page, affs_get_block);
return block_write_full_page(page, affs_get_block, wbc);
}
static int affs_readpage(struct file *file, struct page *page)
{
......
......@@ -130,9 +130,9 @@ static int bfs_get_block(struct inode * inode, sector_t block,
return err;
}
static int bfs_writepage(struct page *page)
static int bfs_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page, bfs_get_block);
return block_write_full_page(page, bfs_get_block, wbc);
}
static int bfs_readpage(struct file *file, struct page *page)
......
......@@ -126,9 +126,9 @@ blkdev_direct_IO(int rw, struct file *file, const struct iovec *iov,
nr_segs, blkdev_get_blocks);
}
static int blkdev_writepage(struct page * page)
static int blkdev_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page, blkdev_get_block);
return block_write_full_page(page, blkdev_get_block, wbc);
}
static int blkdev_readpage(struct file * file, struct page * page)
......
......@@ -1632,8 +1632,8 @@ EXPORT_SYMBOL(unmap_underlying_metadata);
* with submit_bh(). At the address_space level PageWriteback prevents this
* contention from occurring.
*/
static int __block_write_full_page(struct inode *inode,
struct page *page, get_block_t *get_block)
static int __block_write_full_page(struct inode *inode, struct page *page,
get_block_t *get_block, struct writeback_control *wbc)
{
int err;
unsigned long block;
......@@ -1705,7 +1705,7 @@ static int __block_write_full_page(struct inode *inode,
do {
get_bh(bh);
if (buffer_mapped(bh) && buffer_dirty(bh)) {
if (called_for_sync()) {
if (wbc->sync_mode != WB_SYNC_NONE) {
lock_buffer(bh);
} else {
if (test_set_buffer_locked(bh)) {
......@@ -2485,7 +2485,8 @@ int block_truncate_page(struct address_space *mapping,
/*
* The generic ->writepage function for buffer-backed address_spaces
*/
int block_write_full_page(struct page *page, get_block_t *get_block)
int block_write_full_page(struct page *page, get_block_t *get_block,
struct writeback_control *wbc)
{
struct inode * const inode = page->mapping->host;
const unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
......@@ -2494,7 +2495,7 @@ int block_write_full_page(struct page *page, get_block_t *get_block)
/* Is the page fully inside i_size? */
if (page->index < end_index)
return __block_write_full_page(inode, page, get_block);
return __block_write_full_page(inode, page, get_block, wbc);
/* Is the page fully outside i_size? (truncate in progress) */
offset = inode->i_size & (PAGE_CACHE_SIZE-1);
......@@ -2514,7 +2515,7 @@ int block_write_full_page(struct page *page, get_block_t *get_block)
memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
flush_dcache_page(page);
kunmap_atomic(kaddr, KM_USER0);
return __block_write_full_page(inode, page, get_block);
return __block_write_full_page(inode, page, get_block, wbc);
}
sector_t generic_block_bmap(struct address_space *mapping, sector_t block,
......
......@@ -415,7 +415,7 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
}
static int
cifs_writepage(struct page* page)
cifs_writepage(struct page* page, struct writeback_control *wbc)
{
int rc = -EFAULT;
int xid;
......
......@@ -588,9 +588,9 @@ static int ext2_get_block(struct inode *inode, sector_t iblock, struct buffer_he
goto reread;
}
static int ext2_writepage(struct page *page)
static int ext2_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page,ext2_get_block);
return block_write_full_page(page, ext2_get_block, wbc);
}
static int ext2_readpage(struct file *file, struct page *page)
......
......@@ -33,6 +33,7 @@
#include <linux/quotaops.h>
#include <linux/string.h>
#include <linux/buffer_head.h>
#include <linux/writeback.h>
#include <linux/mpage.h>
#include <linux/uio.h>
#include "xattr.h"
......@@ -1287,7 +1288,7 @@ static int bget_one(handle_t *handle, struct buffer_head *bh)
* disastrous. Any write() or metadata operation will sync the fs for
* us.
*/
static int ext3_writepage(struct page *page)
static int ext3_writepage(struct page *page, struct writeback_control *wbc)
{
struct inode *inode = page->mapping->host;
struct buffer_head *page_bufs;
......@@ -1308,7 +1309,7 @@ static int ext3_writepage(struct page *page)
goto out_fail;
needed = ext3_writepage_trans_blocks(inode);
if (current->flags & PF_MEMALLOC)
if (wbc->for_reclaim)
handle = ext3_journal_try_start(inode, needed);
else
handle = ext3_journal_start(inode, needed);
......@@ -1339,7 +1340,7 @@ static int ext3_writepage(struct page *page)
PAGE_CACHE_SIZE, NULL, bget_one);
}
ret = block_write_full_page(page, ext3_get_block);
ret = block_write_full_page(page, ext3_get_block, wbc);
/*
* The page can become unlocked at any point now, and
......
......@@ -1050,9 +1050,9 @@ static int is_exec(char *extension)
return 0;
}
static int fat_writepage(struct page *page)
static int fat_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page,fat_get_block);
return block_write_full_page(page,fat_get_block, wbc);
}
static int fat_readpage(struct file *file, struct page *page)
{
......
......@@ -229,9 +229,9 @@ int hfs_notify_change_hdr(struct dentry *dentry, struct iattr * attr)
return __hfs_notify_change(dentry, attr, HFS_HDR);
}
static int hfs_writepage(struct page *page)
static int hfs_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page,hfs_get_block);
return block_write_full_page(page,hfs_get_block, wbc);
}
static int hfs_readpage(struct file *file, struct page *page)
{
......
......@@ -98,9 +98,9 @@ int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_
return 0;
}
static int hpfs_writepage(struct page *page)
static int hpfs_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page,hpfs_get_block);
return block_write_full_page(page,hpfs_get_block, wbc);
}
static int hpfs_readpage(struct file *file, struct page *page)
{
......
......@@ -277,9 +277,9 @@ static int jfs_get_block(struct inode *ip, sector_t lblock,
return jfs_get_blocks(ip, lblock, 1, bh_result, create);
}
static int jfs_writepage(struct page *page)
static int jfs_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page, jfs_get_block);
return block_write_full_page(page, jfs_get_block, wbc);
}
static int jfs_writepages(struct address_space *mapping,
......
......@@ -316,9 +316,9 @@ static int minix_get_block(struct inode *inode, sector_t block,
return V2_minix_get_block(inode, block, bh_result, create);
}
static int minix_writepage(struct page *page)
static int minix_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page,minix_get_block);
return block_write_full_page(page, minix_get_block, wbc);
}
static int minix_readpage(struct file *file, struct page *page)
{
......
......@@ -327,7 +327,7 @@ EXPORT_SYMBOL(mpage_readpage);
*/
static struct bio *
mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block,
sector_t *last_block_in_bio, int *ret)
sector_t *last_block_in_bio, int *ret, struct writeback_control *wbc)
{
struct inode *inode = page->mapping->host;
const unsigned blkbits = inode->i_blkbits;
......@@ -501,7 +501,7 @@ mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block,
confused:
if (bio)
bio = mpage_bio_submit(WRITE, bio);
*ret = page->mapping->a_ops->writepage(page);
*ret = page->mapping->a_ops->writepage(page, wbc);
out:
return bio;
}
......@@ -554,9 +554,8 @@ mpage_writepages(struct address_space *mapping,
sector_t last_block_in_bio = 0;
int ret = 0;
int done = 0;
int sync = called_for_sync();
struct pagevec pvec;
int (*writepage)(struct page *);
int (*writepage)(struct page *page, struct writeback_control *wbc);
if (wbc->nonblocking && bdi_write_congested(bdi)) {
blk_run_queues();
......@@ -574,7 +573,7 @@ mpage_writepages(struct address_space *mapping,
struct page *page = list_entry(mapping->io_pages.prev,
struct page, list);
list_del(&page->list);
if (PageWriteback(page) && !sync) {
if (PageWriteback(page) && wbc->sync_mode == WB_SYNC_NONE) {
if (PageDirty(page)) {
list_add(&page->list, &mapping->dirty_pages);
continue;
......@@ -600,16 +599,16 @@ mpage_writepages(struct address_space *mapping,
lock_page(page);
if (sync)
if (wbc->sync_mode != WB_SYNC_NONE)
wait_on_page_writeback(page);
if (page->mapping == mapping && !PageWriteback(page) &&
test_clear_page_dirty(page)) {
if (writepage) {
ret = (*writepage)(page);
ret = (*writepage)(page, wbc);
} else {
bio = mpage_writepage(bio, page, get_block,
&last_block_in_bio, &ret);
&last_block_in_bio, &ret, wbc);
}
if (ret || (--(wbc->nr_to_write) <= 0))
done = 1;
......
......@@ -240,7 +240,7 @@ nfs_writepage_async(struct file *file, struct inode *inode, struct page *page,
* Write an mmapped page to the server.
*/
int
nfs_writepage(struct page *page)
nfs_writepage(struct page *page, struct writeback_control *wbc)
{
struct inode *inode = page->mapping->host;
unsigned long end_index;
......
......@@ -792,7 +792,7 @@ static int ntfs_write_block(struct page *page)
*
* Return 0 on success and -errno on error.
*/
static int ntfs_writepage(struct page *page)
static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
{
s64 attr_pos;
struct inode *vi;
......
......@@ -424,9 +424,9 @@ static void qnx4_put_super(struct super_block *sb)
return;
}
static int qnx4_writepage(struct page *page)
static int qnx4_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page,qnx4_get_block);
return block_write_full_page(page,qnx4_get_block, wbc);
}
static int qnx4_readpage(struct file *file, struct page *page)
{
......
......@@ -1917,7 +1917,7 @@ static inline void submit_bh_for_writepage(struct buffer_head **bhp, int nr) {
}
}
static int reiserfs_write_full_page(struct page *page) {
static int reiserfs_write_full_page(struct page *page, struct writeback_control *wbc) {
struct inode *inode = page->mapping->host ;
unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT ;
unsigned last_offset = PAGE_CACHE_SIZE;
......@@ -2018,11 +2018,11 @@ static int reiserfs_readpage (struct file *f, struct page * page)
}
static int reiserfs_writepage (struct page * page)
static int reiserfs_writepage (struct page * page, struct writeback_control *wbc)
{
struct inode *inode = page->mapping->host ;
reiserfs_wait_on_write_block(inode->i_sb) ;
return reiserfs_write_full_page(page) ;
return reiserfs_write_full_page(page, wbc) ;
}
......
......@@ -170,7 +170,7 @@ smb_writepage_sync(struct inode *inode, struct page *page,
* We are called with the page locked and we unlock it when done.
*/
static int
smb_writepage(struct page *page)
smb_writepage(struct page *page, struct writeback_control *wbc)
{
struct address_space *mapping = page->mapping;
struct inode *inode;
......
......@@ -449,9 +449,9 @@ int sysv_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
return 0;
}
static int sysv_writepage(struct page *page)
static int sysv_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page,get_block);
return block_write_full_page(page,get_block,wbc);
}
static int sysv_readpage(struct file *file, struct page *page)
{
......
......@@ -62,7 +62,7 @@ static int udf_adinicb_readpage(struct file *file, struct page * page)
return 0;
}
static int udf_adinicb_writepage(struct page *page)
static int udf_adinicb_writepage(struct page *page, struct writeback_control *wbc)
{
struct inode *inode = page->mapping->host;
char *kaddr;
......
......@@ -39,6 +39,7 @@
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/buffer_head.h>
#include <linux/writeback.h>
#include <linux/slab.h>
#include "udf_i.h"
......@@ -137,9 +138,9 @@ void udf_discard_prealloc(struct inode * inode)
}
}
static int udf_writepage(struct page *page)
static int udf_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page, udf_get_block);
return block_write_full_page(page, udf_get_block, wbc);
}
static int udf_readpage(struct file *file, struct page *page)
......@@ -170,6 +171,10 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
{
struct page *page;
char *kaddr;
struct writeback_control udf_wbc = {
.sync_mode = WB_SYNC_NONE,
.nr_to_write = 1,
};
/* from now on we have normal address_space methods */
inode->i_data.a_ops = &udf_aops;
......@@ -206,7 +211,7 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
else
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
inode->i_data.a_ops->writepage(page);
inode->i_data.a_ops->writepage(page, &udf_wbc);
page_cache_release(page);
mark_inode_dirty(inode);
......
......@@ -445,9 +445,9 @@ struct buffer_head * ufs_bread (struct inode * inode, unsigned fragment,
return NULL;
}
static int ufs_writepage(struct page *page)
static int ufs_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page,ufs_getfrag_block);
return block_write_full_page(page,ufs_getfrag_block,wbc);
}
static int ufs_readpage(struct file *file, struct page *page)
{
......
......@@ -691,7 +691,8 @@ count_page_state(
STATIC int
linvfs_writepage(
struct page *page)
struct page *page,
struct writeback_control *wbc)
{
int error;
int need_trans = 1;
......
......@@ -178,7 +178,7 @@ extern int buffer_heads_over_limit;
*/
int try_to_release_page(struct page * page, int gfp_mask);
int block_invalidatepage(struct page *page, unsigned long offset);
int block_write_full_page(struct page*, get_block_t*);
int block_write_full_page(struct page *page, get_block_t *get_block, struct writeback_control *wbc);
int block_read_full_page(struct page*, get_block_t*);
int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*);
int cont_prepare_write(struct page*, unsigned, unsigned, get_block_t*,
......
......@@ -278,7 +278,7 @@ struct address_space;
struct writeback_control;
struct address_space_operations {
int (*writepage)(struct page *);
int (*writepage)(struct page *page, struct writeback_control *wbc);
int (*readpage)(struct file *, struct page *);
int (*sync_page)(struct page *);
......
......@@ -291,7 +291,7 @@ extern void nfs_complete_unlink(struct dentry *);
/*
* linux/fs/nfs/write.c
*/
extern int nfs_writepage(struct page *);
extern int nfs_writepage(struct page *page, struct writeback_control *wbc);
extern int nfs_writepages(struct address_space *, struct writeback_control *);
extern int nfs_flush_incompatible(struct file *file, struct page *page);
extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
......
......@@ -424,9 +424,8 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
#define PF_FREEZE 0x00008000 /* this task should be frozen for suspend */
#define PF_IOTHREAD 0x00010000 /* this thread is needed for doing I/O to swap */
#define PF_FROZEN 0x00020000 /* frozen for system suspend */
#define PF_SYNC 0x00040000 /* performing fsync(), etc */
#define PF_FSTRANS 0x00080000 /* inside a filesystem transaction */
#define PF_KSWAPD 0x00100000 /* I am kswapd */
#define PF_FSTRANS 0x00040000 /* inside a filesystem transaction */
#define PF_KSWAPD 0x00080000 /* I am kswapd */
/*
* Ptrace flags
......
......@@ -65,6 +65,7 @@ typedef struct {
struct sysinfo;
struct address_space;
struct zone;
struct writeback_control;
/*
* A swap extent maps a range of a swapfile's PAGE_SIZE pages onto a range of
......@@ -180,7 +181,7 @@ extern int shmem_unuse(swp_entry_t entry, struct page *page);
#ifdef CONFIG_SWAP
/* linux/mm/page_io.c */
extern int swap_readpage(struct file *, struct page *);
extern int swap_writepage(struct page *);
extern int swap_writepage(struct page *page, struct writeback_control *wbc);
extern int rw_swap_page_sync(int, swp_entry_t, struct page *);
/* linux/mm/swap_state.c */
......
......@@ -42,6 +42,7 @@ struct writeback_control {
int nonblocking; /* Don't get stuck on request queues */
int encountered_congestion; /* An output: a queue is full */
int for_kupdate; /* A kupdate writeback */
int for_reclaim; /* Invoked from the page allocator */
};
/*
......@@ -88,13 +89,4 @@ extern int nr_pdflush_threads; /* Global so it can be exported to sysctl
read-only. */
/*
* Tell the writeback paths that they are being called for a "data integrity"
* operation such as fsync().
*/
static inline int called_for_sync(void)
{
return current->flags & PF_SYNC;
}
#endif /* WRITEBACK_H */
......@@ -117,10 +117,6 @@ static inline int sync_page(struct page *page)
* cleansing writeback. The difference between these two operations is that
* if a dirty page/buffer is encountered, it must be waited upon, and not just
* skipped over.
*
* The PF_SYNC flag is set across this operation and the various functions
* which care about this distinction must use called_for_sync() to find out
* which behaviour they should implement.
*/
int filemap_fdatawrite(struct address_space *mapping)
{
......@@ -133,12 +129,10 @@ int filemap_fdatawrite(struct address_space *mapping)
if (mapping->backing_dev_info->memory_backed)
return 0;
current->flags |= PF_SYNC;
write_lock(&mapping->page_lock);
list_splice_init(&mapping->dirty_pages, &mapping->io_pages);
write_unlock(&mapping->page_lock);
ret = do_writepages(mapping, &wbc);
current->flags &= ~PF_SYNC;
return ret;
}
......
......@@ -412,6 +412,9 @@ int write_one_page(struct page *page, int wait)
{
struct address_space *mapping = page->mapping;
int ret = 0;
struct writeback_control wbc = {
.sync_mode = WB_SYNC_ALL,
};
BUG_ON(!PageLocked(page));
......@@ -424,7 +427,7 @@ int write_one_page(struct page *page, int wait)
list_add(&page->list, &mapping->locked_pages);
page_cache_get(page);
write_unlock(&mapping->page_lock);
ret = mapping->a_ops->writepage(page);
ret = mapping->a_ops->writepage(page, &wbc);
if (ret == 0 && wait) {
wait_on_page_writeback(page);
if (PageError(page))
......
......@@ -18,6 +18,7 @@
#include <linux/swapops.h>
#include <linux/buffer_head.h> /* for block_sync_page() */
#include <linux/mpage.h>
#include <linux/writeback.h>
#include <asm/pgtable.h>
static struct bio *
......@@ -86,7 +87,7 @@ static int end_swap_bio_read(struct bio *bio, unsigned int bytes_done, int err)
* We may have stale swap cache pages in memory: notice
* them here and get rid of the unnecessary final write.
*/
int swap_writepage(struct page *page)
int swap_writepage(struct page *page, struct writeback_control *wbc)
{
struct bio *bio;
int ret = 0;
......@@ -143,6 +144,9 @@ struct address_space_operations swap_aops = {
int rw_swap_page_sync(int rw, swp_entry_t entry, struct page *page)
{
int ret;
struct writeback_control swap_wbc = {
.sync_mode = WB_SYNC_ALL,
};
lock_page(page);
......@@ -154,7 +158,7 @@ int rw_swap_page_sync(int rw, swp_entry_t entry, struct page *page)
ret = swap_readpage(NULL, page);
wait_on_page_locked(page);
} else {
ret = swap_writepage(page);
ret = swap_writepage(page, &swap_wbc);
wait_on_page_writeback(page);
}
page->mapping = NULL;
......
......@@ -671,7 +671,7 @@ int shmem_unuse(swp_entry_t entry, struct page *page)
/*
* Move the page from the page cache to the swap cache.
*/
static int shmem_writepage(struct page *page)
static int shmem_writepage(struct page *page, struct writeback_control *wbc)
{
struct shmem_inode_info *info;
swp_entry_t *entry, swap;
......
......@@ -16,6 +16,7 @@
#include <linux/shm.h>
#include <linux/blkdev.h>
#include <linux/buffer_head.h>
#include <linux/writeback.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/init.h>
......@@ -696,7 +697,11 @@ static int try_to_unuse(unsigned int type)
* and now we must reincrement count to try again later.
*/
if ((*swap_map > 1) && PageDirty(page) && PageSwapCache(page)) {
swap_writepage(page);
struct writeback_control wbc = {
.sync_mode = WB_SYNC_NONE,
};
swap_writepage(page, &wbc);
lock_page(page);
wait_on_page_writeback(page);
}
......
......@@ -319,13 +319,19 @@ shrink_list(struct list_head *page_list, unsigned int gfp_mask,
goto keep_locked;
if (test_clear_page_dirty(page)) {
int res;
struct writeback_control wbc = {
.sync_mode = WB_SYNC_NONE,
.nr_to_write = SWAP_CLUSTER_MAX,
.nonblocking = 1,
.for_reclaim = 1,
};
write_lock(&mapping->page_lock);
list_move(&page->list, &mapping->locked_pages);
write_unlock(&mapping->page_lock);
SetPageReclaim(page);
res = mapping->a_ops->writepage(page);
res = mapping->a_ops->writepage(page, &wbc);
if (res == WRITEPAGE_ACTIVATE) {
ClearPageReclaim(page);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment