]> git.hungrycats.org Git - linux/commitdiff
[PATCH] sync dirty pages in fadvise(FADV_DONTNEED)
authorAndrew Morton <akpm@digeo.com>
Thu, 3 Apr 2003 00:28:11 +0000 (16:28 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Thu, 3 Apr 2003 00:28:11 +0000 (16:28 -0800)
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.

include/linux/fs.h
mm/fadvise.c
mm/filemap.c

index 5594259b2795a140e05e708c1e26f27bf1df3d8e..3ee3bf870ff182e7da0c4a549e6a9b1cea5ed3c0 100644 (file)
@@ -1112,6 +1112,7 @@ unsigned long invalidate_inode_pages(struct address_space *mapping);
 extern void invalidate_inode_pages2(struct address_space *mapping);
 extern void write_inode_now(struct inode *, int);
 extern int filemap_fdatawrite(struct address_space *);
+extern int filemap_flush(struct address_space *);
 extern int filemap_fdatawait(struct address_space *);
 extern void sync_supers(void);
 extern void sync_filesystems(int wait);
index a14b89271e80c5ff3b4c7895f4d7bb20bc562bf9..cb0f8a158f93a2ee45330c03fce0ced476c34574 100644 (file)
@@ -61,6 +61,8 @@ long sys_fadvise64(int fd, loff_t offset, size_t len, int advice)
                        ret = 0;
                break;
        case POSIX_FADV_DONTNEED:
+               if (!bdi_write_congested(mapping->backing_dev_info))
+                       filemap_flush(mapping);
                invalidate_mapping_pages(mapping, offset >> PAGE_CACHE_SHIFT,
                                (len >> PAGE_CACHE_SHIFT) + 1);
                break;
index 3edc0628638a15c9e7f7e9be5e423938575b0e1c..65d10150f68ca4310880c68740c00cbb59072aae 100644 (file)
@@ -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
  * skipped over.
  */
-int filemap_fdatawrite(struct address_space *mapping)
+static int __filemap_fdatawrite(struct address_space *mapping, int sync_mode)
 {
        int ret;
        struct writeback_control wbc = {
-               .sync_mode = WB_SYNC_ALL,
+               .sync_mode = sync_mode,
                .nr_to_write = mapping->nrpages * 2,
        };
 
@@ -140,6 +140,20 @@ int filemap_fdatawrite(struct address_space *mapping)
        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
  *                     space and wait for all of them.