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