The backing_dev_info `memory_backed' boolean is presently overloaded.  It
means both "dirty pages against this device do not contribute to dirty memory
accounting" and "there is no point in performing writeback against files which
are backed by this device"

Both rules indeed hold true for ramfs-type filesystems.  But they need to be
separated for the ramdisk device.  ramdisk-backed files should not contribute
to dirty memory but they should get writeback, so we copy data from the
regular files' pagecache into the ramdisk blockdev pagecache.

Except this still isn't right :(

Really, we want regular files which are backed by a ramdisk device to
contribute to dirty memory so that the VM will write them into the ramdisk
blockdev pagecache.  But we don't want the ramdisk blockdev address_space's
dirty pages to contribute to dirty memory, because we have no way of cleaning
them again.  (their dirtiness is the only thing which keeps these pages from
being reclaimed by the VM).

Ho hum, it's probably OK.  kupdate and sync() and VM pressure will still do
the right thing.

This patch makes no functional changes to anything.


---

 25-akpm/arch/ia64/sn/io/hwgfs/ramfs.c |    3 ++-
 25-akpm/drivers/block/ll_rw_blk.c     |    3 ++-
 25-akpm/drivers/block/rd.c            |    3 ++-
 25-akpm/fs/buffer.c                   |    2 +-
 25-akpm/fs/fs-writeback.c             |    2 +-
 25-akpm/fs/hugetlbfs/inode.c          |    3 ++-
 25-akpm/fs/ramfs/inode.c              |    3 ++-
 25-akpm/fs/sysfs/inode.c              |    3 ++-
 25-akpm/include/linux/backing-dev.h   |   10 +++++++++-
 25-akpm/mm/filemap.c                  |    2 +-
 25-akpm/mm/page-writeback.c           |    6 +++---
 25-akpm/mm/shmem.c                    |    3 ++-
 25-akpm/mm/swap_state.c               |    3 ++-
 13 files changed, 31 insertions(+), 15 deletions(-)

diff -puN arch/ia64/sn/io/hwgfs/ramfs.c~split-backing_dev-memory-backed arch/ia64/sn/io/hwgfs/ramfs.c
--- 25/arch/ia64/sn/io/hwgfs/ramfs.c~split-backing_dev-memory-backed	2004-05-17 18:04:46.949590104 -0700
+++ 25-akpm/arch/ia64/sn/io/hwgfs/ramfs.c	2004-05-17 18:04:46.968587216 -0700
@@ -29,7 +29,8 @@ static struct inode_operations hwgfs_dir
 
 static struct backing_dev_info hwgfs_backing_dev_info = {
 	.ra_pages       = 0,	/* No readahead */
-	.memory_backed  = 1,	/* Does not contribute to dirty memory */
+	.no_dirty_acct  = 1,	/* Does not contribute to dirty memory */
+	.no_writeback	= 1,	/* Does not need writeback */
 };
 
 static struct inode *hwgfs_get_inode(struct super_block *sb, int mode, dev_t dev)
diff -puN drivers/block/ll_rw_blk.c~split-backing_dev-memory-backed drivers/block/ll_rw_blk.c
--- 25/drivers/block/ll_rw_blk.c~split-backing_dev-memory-backed	2004-05-17 18:04:46.951589800 -0700
+++ 25-akpm/drivers/block/ll_rw_blk.c	2004-05-17 18:04:46.971586760 -0700
@@ -242,7 +242,8 @@ void blk_queue_make_request(request_queu
 	q->make_request_fn = mfn;
 	q->backing_dev_info.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
 	q->backing_dev_info.state = 0;
-	q->backing_dev_info.memory_backed = 0;
+	q->backing_dev_info.no_dirty_acct = 0;
+	q->backing_dev_info.no_writeback = 0;
 	blk_queue_max_sectors(q, MAX_SECTORS);
 	blk_queue_hardsect_size(q, 512);
 	blk_queue_dma_alignment(q, 511);
diff -puN drivers/block/rd.c~split-backing_dev-memory-backed drivers/block/rd.c
--- 25/drivers/block/rd.c~split-backing_dev-memory-backed	2004-05-17 18:04:46.952589648 -0700
+++ 25-akpm/drivers/block/rd.c	2004-05-17 18:27:46.625847432 -0700
@@ -270,7 +270,8 @@ static int rd_ioctl(struct inode *inode,
 
 static struct backing_dev_info rd_backing_dev_info = {
 	.ra_pages	= 0,	/* No readahead */
-	.memory_backed	= 1,	/* Does not contribute to dirty memory */
+	.no_dirty_acct	= 1,	/* Does not contribute to dirty memory */
+	.no_writeback	= 1,	/* Does not need writeback */
 	.unplug_io_fn = default_unplug_io_fn,
 };
 
diff -puN include/linux/backing-dev.h~split-backing_dev-memory-backed include/linux/backing-dev.h
--- 25/include/linux/backing-dev.h~split-backing_dev-memory-backed	2004-05-17 18:04:46.954589344 -0700
+++ 25-akpm/include/linux/backing-dev.h	2004-05-17 18:04:46.972586608 -0700
@@ -22,10 +22,18 @@ enum bdi_state {
 
 typedef int (congested_fn)(void *, int);
 
+/*
+ * `no_writeback' means that there is no point in the VM trying to write back
+ * pages against this device: their backing store is their own pagecache.
+ *
+ * `no_dirty_acct' means that marking a page dirty against this device does
+ * not contribute to page_state.nr_dirty, nor to /proc/meminfo:Dirty.
+ */
 struct backing_dev_info {
 	unsigned long ra_pages;	/* max readahead in PAGE_CACHE_SIZE units */
 	unsigned long state;	/* Always use atomic bitops on this */
-	int memory_backed;	/* Cannot clean pages with writepage */
+	int no_dirty_acct;	/* Does not contribute to dirty accounting */
+	int no_writeback;	/* Cannot clean pages with writepage */
 	congested_fn *congested_fn; /* Function pointer if device is md/dm */
 	void *congested_data;	/* Pointer to aux data for congested func */
 	void (*unplug_io_fn)(struct backing_dev_info *, struct page *);
diff -puN fs/sysfs/inode.c~split-backing_dev-memory-backed fs/sysfs/inode.c
--- 25/fs/sysfs/inode.c~split-backing_dev-memory-backed	2004-05-17 18:04:46.955589192 -0700
+++ 25-akpm/fs/sysfs/inode.c	2004-05-17 18:04:46.972586608 -0700
@@ -23,7 +23,8 @@ static struct address_space_operations s
 
 static struct backing_dev_info sysfs_backing_dev_info = {
 	.ra_pages	= 0,	/* No readahead */
-	.memory_backed	= 1,	/* Does not contribute to dirty memory */
+	.no_dirty_acct	= 1,	/* Does not contribute to dirty memory */
+	.no_writeback	= 1,	/* Does not need VM writeback */
 };
 
 struct inode * sysfs_new_inode(mode_t mode)
diff -puN fs/hugetlbfs/inode.c~split-backing_dev-memory-backed fs/hugetlbfs/inode.c
--- 25/fs/hugetlbfs/inode.c~split-backing_dev-memory-backed	2004-05-17 18:04:46.956589040 -0700
+++ 25-akpm/fs/hugetlbfs/inode.c	2004-05-17 18:04:46.973586456 -0700
@@ -40,7 +40,8 @@ static struct inode_operations hugetlbfs
 
 static struct backing_dev_info hugetlbfs_backing_dev_info = {
 	.ra_pages	= 0,	/* No readahead */
-	.memory_backed	= 1,	/* Does not contribute to dirty memory */
+	.no_dirty_acct	= 1,	/* Does not contribute to dirty memory */
+	.no_writeback	= 1,	/* Does not need VM writeback */
 };
 
 int sysctl_hugetlb_shm_group;
diff -puN fs/ramfs/inode.c~split-backing_dev-memory-backed fs/ramfs/inode.c
--- 25/fs/ramfs/inode.c~split-backing_dev-memory-backed	2004-05-17 18:04:46.958588736 -0700
+++ 25-akpm/fs/ramfs/inode.c	2004-05-17 18:04:46.973586456 -0700
@@ -45,7 +45,8 @@ static struct inode_operations ramfs_dir
 
 static struct backing_dev_info ramfs_backing_dev_info = {
 	.ra_pages	= 0,	/* No readahead */
-	.memory_backed	= 1,	/* Does not contribute to dirty memory */
+	.no_dirty_acct	= 1,	/* Does not contribute to dirty memory */
+	.no_writeback	= 1,	/* Does not need VM writeback */
 };
 
 static struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
diff -puN fs/buffer.c~split-backing_dev-memory-backed fs/buffer.c
--- 25/fs/buffer.c~split-backing_dev-memory-backed	2004-05-17 18:04:46.959588584 -0700
+++ 25-akpm/fs/buffer.c	2004-05-17 18:04:46.976586000 -0700
@@ -949,7 +949,7 @@ int __set_page_dirty_buffers(struct page
 	if (!TestSetPageDirty(page)) {
 		spin_lock_irq(&mapping->tree_lock);
 		if (page->mapping) {	/* Race with truncate? */
-			if (!mapping->backing_dev_info->memory_backed)
+			if (!mapping->backing_dev_info->no_dirty_acct)
 				inc_page_state(nr_dirty);
 			radix_tree_tag_set(&mapping->page_tree,
 						page_index(page),
diff -puN fs/fs-writeback.c~split-backing_dev-memory-backed fs/fs-writeback.c
--- 25/fs/fs-writeback.c~split-backing_dev-memory-backed	2004-05-17 18:04:46.960588432 -0700
+++ 25-akpm/fs/fs-writeback.c	2004-05-17 18:27:46.626847280 -0700
@@ -301,7 +301,7 @@ sync_sb_inodes(struct super_block *sb, s
 		struct backing_dev_info *bdi = mapping->backing_dev_info;
 		long pages_skipped;
 
-		if (bdi->memory_backed) {
+		if (bdi->no_writeback) {
 			if (sb == blockdev_superblock) {
 				/*
 				 * Dirty memory-backed blockdev: the ramdisk
diff -puN mm/filemap.c~split-backing_dev-memory-backed mm/filemap.c
--- 25/mm/filemap.c~split-backing_dev-memory-backed	2004-05-17 18:04:46.962588128 -0700
+++ 25-akpm/mm/filemap.c	2004-05-17 18:04:47.128562896 -0700
@@ -150,7 +150,7 @@ static int __filemap_fdatawrite(struct a
 		.nr_to_write = mapping->nrpages * 2,
 	};
 
-	if (mapping->backing_dev_info->memory_backed)
+	if (mapping->backing_dev_info->no_writeback)
 		return 0;
 
 	ret = do_writepages(mapping, &wbc);
diff -puN mm/shmem.c~split-backing_dev-memory-backed mm/shmem.c
--- 25/mm/shmem.c~split-backing_dev-memory-backed	2004-05-17 18:04:46.964587824 -0700
+++ 25-akpm/mm/shmem.c	2004-05-17 18:04:47.130562592 -0700
@@ -172,7 +172,8 @@ static struct vm_operations_struct shmem
 
 static struct backing_dev_info shmem_backing_dev_info = {
 	.ra_pages	= 0,	/* No readahead */
-	.memory_backed	= 1,	/* Does not contribute to dirty memory */
+	.no_dirty_acct	= 1,	/* Does not contribute to dirty memory */
+	.no_writeback	= 1,	/* Does not need VM writeback */
 	.unplug_io_fn = default_unplug_io_fn,
 };
 
diff -puN mm/page-writeback.c~split-backing_dev-memory-backed mm/page-writeback.c
--- 25/mm/page-writeback.c~split-backing_dev-memory-backed	2004-05-17 18:04:46.965587672 -0700
+++ 25-akpm/mm/page-writeback.c	2004-05-17 18:04:47.131562440 -0700
@@ -570,7 +570,7 @@ int __set_page_dirty_nobuffers(struct pa
 			mapping = page_mapping(page);
 			if (page_mapping(page)) { /* Race with truncate? */
 				BUG_ON(page_mapping(page) != mapping);
-				if (!mapping->backing_dev_info->memory_backed)
+				if (!mapping->backing_dev_info->no_dirty_acct)
 					inc_page_state(nr_dirty);
 				radix_tree_tag_set(&mapping->page_tree,
 					page_index(page), PAGECACHE_TAG_DIRTY);
@@ -656,7 +656,7 @@ int test_clear_page_dirty(struct page *p
 						page_index(page),
 						PAGECACHE_TAG_DIRTY);
 			spin_unlock_irqrestore(&mapping->tree_lock, flags);
-			if (!mapping->backing_dev_info->memory_backed)
+			if (!mapping->backing_dev_info->no_dirty_acct)
 				dec_page_state(nr_dirty);
 			return 1;
 		}
@@ -687,7 +687,7 @@ int clear_page_dirty_for_io(struct page 
 
 	if (mapping) {
 		if (TestClearPageDirty(page)) {
-			if (!mapping->backing_dev_info->memory_backed)
+			if (!mapping->backing_dev_info->no_dirty_acct)
 				dec_page_state(nr_dirty);
 			return 1;
 		}
diff -puN mm/swap_state.c~split-backing_dev-memory-backed mm/swap_state.c
--- 25/mm/swap_state.c~split-backing_dev-memory-backed	2004-05-17 18:27:59.679862920 -0700
+++ 25-akpm/mm/swap_state.c	2004-05-17 18:28:32.211917296 -0700
@@ -28,7 +28,8 @@ static struct address_space_operations s
 };
 
 static struct backing_dev_info swap_backing_dev_info = {
-	.memory_backed	= 1,	/* Does not contribute to dirty memory */
+	.no_dirty_acct	= 1,	/* Does not contribute to dirty memory */
+	.no_writeback	= 1,	/* Does not need VM writeback */
 	.unplug_io_fn	= swap_unplug_io_fn,
 };
 

_