Commit 3bc17e74 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] sync dirty pages in fadvise(FADV_DONTNEED)

This changes the fadvise(FADV_DONTNEED) operation to start async writeout of
any dirty pages in the file.

The thinking is that if the application doesn't want to use those pages in
the future, we may as well get IO underway against them so they can be freed
up on the next call to fadvise().

The POSIX spec does not go into any detail as to whether this is the right or
wrong behaviour.

This provides a nice way for applications whihc are writing streaming data
(the main users of fadvise) to keep the amount of dirty pagecache under
control without having to resort to system-wide VM tuning.

It also provides an "async fsync()".  If the application passes in a length
of zero, fadvise will start async writeout of the pages, but will not
invalidate any of the file's pagecache.
parent 89ef9495
...@@ -1112,6 +1112,7 @@ unsigned long invalidate_inode_pages(struct address_space *mapping); ...@@ -1112,6 +1112,7 @@ unsigned long invalidate_inode_pages(struct address_space *mapping);
extern void invalidate_inode_pages2(struct address_space *mapping); extern void invalidate_inode_pages2(struct address_space *mapping);
extern void write_inode_now(struct inode *, int); extern void write_inode_now(struct inode *, int);
extern int filemap_fdatawrite(struct address_space *); extern int filemap_fdatawrite(struct address_space *);
extern int filemap_flush(struct address_space *);
extern int filemap_fdatawait(struct address_space *); extern int filemap_fdatawait(struct address_space *);
extern void sync_supers(void); extern void sync_supers(void);
extern void sync_filesystems(int wait); extern void sync_filesystems(int wait);
......
...@@ -61,6 +61,8 @@ long sys_fadvise64(int fd, loff_t offset, size_t len, int advice) ...@@ -61,6 +61,8 @@ long sys_fadvise64(int fd, loff_t offset, size_t len, int advice)
ret = 0; ret = 0;
break; break;
case POSIX_FADV_DONTNEED: case POSIX_FADV_DONTNEED:
if (!bdi_write_congested(mapping->backing_dev_info))
filemap_flush(mapping);
invalidate_mapping_pages(mapping, offset >> PAGE_CACHE_SHIFT, invalidate_mapping_pages(mapping, offset >> PAGE_CACHE_SHIFT,
(len >> PAGE_CACHE_SHIFT) + 1); (len >> PAGE_CACHE_SHIFT) + 1);
break; break;
......
...@@ -122,11 +122,11 @@ static inline int sync_page(struct page *page) ...@@ -122,11 +122,11 @@ static inline int sync_page(struct page *page)
* 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.
*/ */
int filemap_fdatawrite(struct address_space *mapping) static int __filemap_fdatawrite(struct address_space *mapping, int sync_mode)
{ {
int ret; int ret;
struct writeback_control wbc = { struct writeback_control wbc = {
.sync_mode = WB_SYNC_ALL, .sync_mode = sync_mode,
.nr_to_write = mapping->nrpages * 2, .nr_to_write = mapping->nrpages * 2,
}; };
...@@ -140,6 +140,20 @@ int filemap_fdatawrite(struct address_space *mapping) ...@@ -140,6 +140,20 @@ int filemap_fdatawrite(struct address_space *mapping)
return ret; return ret;
} }
int filemap_fdatawrite(struct address_space *mapping)
{
return __filemap_fdatawrite(mapping, WB_SYNC_ALL);
}
/*
* This is a mostly non-blocking flush. Not suitable for data-integrity
* purposes.
*/
int filemap_flush(struct address_space *mapping)
{
return __filemap_fdatawrite(mapping, WB_SYNC_NONE);
}
/** /**
* filemap_fdatawait - walk the list of locked pages of the given address * filemap_fdatawait - walk the list of locked pages of the given address
* space and wait for all of them. * space and wait for all of them.
......
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